I an writing a Programm in Qt which should discover Routers in a LAN via UPnP.
This is the constructor of my class:
Discovery::Discovery(QObject *parent):QObject(parent)
{
groupAddress = QHostAddress("239.255.255.250");
ssdpPort = 1900;
socket = new QUdpSocket(this);
socket->joinMulticastGroup(groupAddress);
connect(socket,SIGNAL(readyRead()),this,SLOT(processPendingDatagrams()));
discovered = new QList<DiscoveryMatch>();
}
After creating, I send out the search message:
void Discovery::discover()
{
QByteArray Data;
Data.append("M-SEARCH * HTTP/1.1\r\n");
Data.append("HOST: 239.255.255.250:1900\r\n");
Data.append("ST: urn:schemas-upnp-org:device:InternetGatewayDevice:1\r\n");
Data.append("MAN: \"ssdp:discover\"\r\n");
Data.append("MX: 5\r\n\r\n");
socket->writeDatagram(Data, groupAddress, ssdpPort);
}
If a device answered, I process the reply with the readyRead() Signal:
void Discovery::processPendingDatagrams()
{
QByteArray buffer;
QHostAddress sender;
quint16 senderPort;
while(socket->hasPendingDatagrams())
{
buffer.resize(socket->pendingDatagramSize());
socket->readDatagram(buffer.data(), buffer.size(),&sender, &senderPort);
qDebug() << "Message from: " << sender.toString();
qDebug() << "Message port: " << senderPort;
qDebug() << "Message " << buffer;
processDatagram(buffer);
}
}
I have 2 Routers in my Network and if I run the Programm the socket reads the Datagram from my DrayTek Router and ignores the response from my FRITZ!Box.
The strange thing is, that if I run the Programm in Debug mode the socket catches both responses as I intended.
Is this a Qt Problem or do I something wrong?
Thank you for reading and for any advise.
Related
I want to receive UDP messages using QT. The code I use (see bellow) works well, but the problem is that it only works for one message: after receiving one message, the code still running, but it seems that it doesn't receive anything anymore.
Indeed, after the first message received, the console display qDebug() << "in !";, meaning that it enters into the function, but never received other UDP messages.
I already check, I sure the message is well sent by the UDP server. So the problem must come from here. Any suggestions?
Launching UDP when the class is created:
App::App(QWidget *parent)
: QMainWindow(parent), imageLabel(new QLabel)
, scrollArea(new QScrollArea)
{
.....
StartUDP();
....
}
The UDP initialization:
void App::StartUDP()
{
socket = new QUdpSocket(this);
bool result = socket->bind(QHostAddress::AnyIPv4, 17);
qDebug() << result;
if(result)
{
qDebug() << "PASS";
}
else
{
qDebug() << "FAIL";
}
readyRead();
connect(socket, SIGNAL(readyRead()), this, SLOT(readyRead()),Qt::QueuedConnection);
}
The function that what for UDP signal:
void App::readyRead()
{
qDebug() << "in !";
QHostAddress sender;
quint16 port;
while (socket->hasPendingDatagrams())
{
QByteArray datagram;
datagram.resize(socket->pendingDatagramSize());
socket->readDatagram(datagram.data(),datagram.size(),&sender,&port);
qDebug() <<"Message From :: " << sender.toString();
qDebug() <<"Port From :: "<< port;
qDebug() <<"Message :: " << datagram;
file_name = datagram;
m_SystemTrayIcon->showMessage(tr("Message"), tr("Nouveau fichier détecté"));
}
}
I'm trying to communicate between 2 devices using bluetooth sockets and rfcomm but my program crashes (see here for error image).
I just listen about 1 or 2 second and then the project just crashes.
This is my client sending audio:
void ClientTalk::startTalk()
{
qDebug() << "Start talk";
audio_output->stop();
connect(audio_input, SIGNAL(stateChanged(QAudio::State)), this, SLOT(handleStateChangedInput(QAudio::State)));
audio_input->start(socket);
qDebug() << "Talking to server";
}
And this is my client listening to server:
void ClientTalk::readSocket()
{
//QBuffer *buffer;
QByteArray buff;
audio_input->stop();
connect(audio_output, SIGNAL(stateChanged(QAudio::State)), this, SLOT(handleStateChangedOutput(QAudio::State)));
while(socket->canReadLine())
{
buff.append(socket->readLine());
QBuffer audio_buffer(&buff);
audio_buffer.open(QIODevice::WriteOnly);
//QDataStream s(buff, QIODevice::ReadWrite);
audio_output->start(&audio_buffer);
qDebug() << buff << endl;
}
buff.clear()
}
And this is my server talk and listen:
void ServerTalk::readSocket()
{
QBluetoothSocket *socket = qobject_cast<QBluetoothSocket *>(sender());
if (!socket)
return;
//QBuffer *buffer;
audio_input->stop();
QByteArray buff;
connect(audio_output, SIGNAL(stateChanged(QAudio::State)), this, SLOT(handleStateChangedOutput(QAudio::State)));
while(socket->canReadLine())
{
buff.append(socket->readLine());
QBuffer audio_buffer(&buff);
audio_buffer.open(QIODevice::WriteOnly);
//QDataStream s(buff, QIODevice::ReadWrite);
audio_output->start(&audio_buffer);
qDebug() << buff << endl;
}
buff.clear();
}
And I have a button to start talk and listen:
connect(btn_talk, SIGNAL(pressed()), server, SLOT(startTalk()));
connect(btn_talk, SIGNAL(released()), server, SLOT(readSocket()));
I am using Qt 4.8 GCC 32bit on xUbuntu 14.04.
I have the following piece of code, a TCP server that I use in order to get some remote commands and send back some answers - via TCP socket:
struct _MyRequest
{
unsigned long Request;
unsigned long Data;
} __attribute__((packed));
struct _MyAnswer
{
unsigned long Error;
unsigned long Filler;
} __attribute__((packed));
_MyRequest request;
_MyAnswer answer;
RemoteCmdServer::RemoteCmdServer(QObject * parent)
: QTcpServer(parent)
{
qDebug() << "Server started";
listen(QHostAddress("172.31.250.110"), 5004);
connect(this, SIGNAL(newConnection()), this, SLOT(processPendingRequest()));
}
void RemoteCmdServer::processPendingRequest()
{
qDebug() << "Process request";
QTcpSocket * clientConnection = nextPendingConnection();
connect(clientConnection, SIGNAL(disconnected()), clientConnection, SLOT(deleteLater()));
// get the request
int ret = clientConnection->read((char*)&request, sizeof(request));
qDebug() << "READ: " << ret;
if(ret == sizeof(request))
{
// send answer
clientConnection->write((char*)&answer, sizeof(answer));
}
qDebug() << "Disconnecting...";
clientConnection->disconnectFromHost();
}
I am able to write correctly if I comment the if(ret == sizeof(request)) line.
Yet, I can't read from the socket (I always get 0 bytes).
I am 100% sure that the TCP-tool I use to send packets to my app works ok.
Here is the debug output from my app:
Server started
Process request
READ: 0
Disconnecting...
What am I doing wrong? Please advise!
You should wait for the data either in a non-blocking or blocking way. You can use waitForReadyRead to do it in a blocking way.
void RemoteCmdServer::processPendingRequest()
{
qDebug() << "Process request";
QTcpSocket * clientConnection = nextPendingConnection();
connect(clientConnection, SIGNAL(disconnected()), clientConnection, SLOT(deleteLater()));
if (clientConnection->waitForReadyRead())
{
// get the request
QByteArray message = clientConnection->readAll(); // Read message
qDebug() << "Message:" << QString(message);
}
else
{
qDebug().nospace() << "ERROR: could not receive message (" << qPrintable(clientConnection->errorString()) << ")";
}
qDebug() << "Disconnecting...";
clientConnection->disconnectFromHost();
}
You're trying to read data from the new connection without returning to the Qt event loop -- I don't think that's going to work.
After you've accepted the connect with...
QTcpSocket * clientConnection = nextPendingConnection();
You need to connect to its readyRead signal with something like...
connect(clientConnection, SIGNAL(readyRead()), this, SLOT(my_read_slot()));
Where my_read_slot is the member function that will actually perform the read operation.
I have a server that can handle multiple threads. The server starts and listens, but it is having trouble echoing when an incoming connection is pending.
I am using telnet to open the socket and send data to the server. However, the server only displays that it's listening, but doesn't echo any of the data I type through telnet or signify that there is an incoming connection. I shut off Windows firewall for private networks and still...nothing.
Also tried seeing if the server error string had anything useful to say, but all it is just an empty string.
This is a complete mystery to me and if anyone had anything constructive to note, it'd be much appreciated. Code for the thread and server is below.
server.cpp
#include "myserver.h"
MyServer::MyServer(QObject *parent) :
QTcpServer(parent)
{
}
void MyServer::StartServer()
{
if(!this->listen(QHostAddress::Any,1234))
{
qDebug() << "Could not start server";
}
else
{
qDebug() << "Listening...";
}
}
void MyServer::incomingConnection(int socketDescriptor)
{
qDebug() << socketDescriptor << " Connecting...";
MyThread *thread = new MyThread(socketDescriptor,this);
connect(thread, SIGNAL(finished()),thread, SLOT(deleteLater()));
thread->start();
}
thread.cpp
#include "mythread.h"
MyThread::MyThread(int ID, QObject *parent) :
QThread(parent)
{ this->socketDescriptor = ID;
}
void MyThread::run()
{
qDebug() << socket->errorString();
//thread starts here
qDebug() << socketDescriptor << " Starting thread";
socket = new QTcpSocket();
if(!socket->setSocketDescriptor(this->socketDescriptor))
{
emit error(socket->error());
return;
}
connect(socket,SIGNAL(readyRead()),this,SLOT(readyRead()),Qt::DirectConnection);
connect(socket,SIGNAL(disconnected()),this,SLOT(disconnected()),Qt::DirectConnection);
qDebug() << socketDescriptor << " Client Connected";
exec();
}
void MyThread::readyRead()
{
QByteArray Data = socket->readAll();
qDebug() << socketDescriptor << " Data in: " << Data;
socket->write(Data);
}
void MyThread::disconnected()
{
qDebug() << socketDescriptor << " Disconnected";
socket->deleteLater();
exit(0);
}
Which version of Qt are you using? In Qt 5, the parameter for the function incomingConnection is of type qintptr and not int. Have a look at the following links:
incomingConnection - Qt 5
Qt 5 - Multithreaded server tutorial
I am currently trying to make a simple "device discovery" app with a PC and a Raspberry Pi. I am using Qt to do this.
Heres the idea...
I have a Qt Application that runs on my PC, I hit a "Search" button to broadcast a UDP packet with a "Request" message as the datagram. Here is the basic UDP.cpp class (im not including the GUI itself).
MyUDP::MyUDP(QObject *parent) :
QObject(parent)
{
qDebug() << "Binding UDP Socket";
socket = new QUdpSocket(this);
socket->bind(QHostAddress::Any, 5000); //bind to 5000
connect(socket, SIGNAL(readyRead()), this, SLOT(readyRead()));
}
void MyUDP::deviceDiscover(){
QByteArray data;
data.append("Request");
qDebug() << "Sending broadcast";
socket->writeDatagram(data, QHostAddress::Broadcast, 5000); //broadcast from port 5000
}
void MyUDP::readyRead(){
QByteArray buffer;
buffer.resize(socket->pendingDatagramSize());
//var to store headers from udp
QHostAddress sender;
quint16 sender_port;
socket->readDatagram(buffer.data(),buffer.size(), &sender, &sender_port);
qDebug() << "Message from " << sender << " port " << sender_port;
qDebug() << "Msg: " << buffer;
if(QString(buffer).compare("PI")==0){
//add to list
emit(updateList(sender.toString()));
}
}
Now on the PI I have a simple console application that is suppose to read broadcast packets and just echo back a "PI" msg.
Here is the PI Code
MyUDP::MyUDP(QObject *parent) :
QObject(parent)
{
qDebug() << "Binding UDP Socket";
socket = new QUdpSocket(this);
socket->bind(QHostAddress::Any, 5000); //bind to 5000
connect(socket, SIGNAL(readyRead()),this, SLOT(readyRead()));
qDebug() << "Ready Read signal connected,sending out broadcast";
QByteArray data;
data.append("PI");
qDebug() << "Sending datagram";
socket->writeDatagram(data, QHostAddress::Broadcast, 5000); //broadcast from port 5000
}
void MyUDP::readyRead(){
QByteArray buffer;
buffer.resize(socket->pendingDatagramSize());
//var to store headers from udp
QHostAddress sender;
quint16 sender_port;
socket->readDatagram(buffer.data(),buffer.size(), &sender, &sender_port);
qDebug() << "Message from " << sender << " port " << sender_port;
qDebug() << "Msg: " << buffer;
if(QString(buffer).compare("Request")==0){
//send back a "PI" msg
QByteArray data;
data.append("PI");
socket->writeDatagram(data, sender, 5000);
}
}
Now When the PI code first runs, it broadcasts an "alive" msg and the PC app gets it no problem.
Here is my start up sequence (starting the PI app while PC is already running)
Message from QHostAddress( "192.168.211.1" ) port 5000
Msg: "Request"
Message from QHostAddress( "192.168.1.111" ) port 5000
Msg: "PI"
Updating list
Now when I use the search button to send a broadcast, the PI side does not receive anything.
I flushed all the rules for iptables and turned off my windows firewall. Any ideas on what would be preventing the PI from receiving broadcasts from windows?
If I run windows-windows, both receive "request" messages when searching.