Currently I am writing an application for Windows 10 to read UDP packets with a QUDPSocket through the Ethernet adapted to thunderbolt.
WireShark and Microsoft UDP Receiver/Sender both see the proper UDP packets and where each sender ip address, port#, local ip address and local port# are.
But whenever I try to use QUDPSocket, it has trouble receiving any packets. The readyRead() is never signaled.
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) {
socket = new QUdpSocket(this);
connect(socket, SIGNAL(readyRead()), this, SLOT(processPendingDatagrams()), Qt::QueuedConnection);
socket->bind(QHostAddress::AnyIPv4, 56666);
}
void MainWindow::processPendingDatagrams()
{
QByteArray array;
QHostAddress sender;
quint16 senderPort;
while (socket->hasPendingDatagrams())
{
array.fill(0, socket->pendingDatagramSize());
socket->readDatagram(array.data(),
array.size(),
&sender,
&senderPort);
qDebug()<<socket->pendingDatagramSize();
}
}
I tried multiple versions of binding but none worked.
Thanks for any help in advance.
Related
Trying to implement a multi thread server in Qt, just consider this:
in SocketThread class:
SocketThread::SocketThread(qintptr descriptor, QObject *parent)
: QThread(parent), socketDescriptor(descriptor)
{
socket = new QTcpSocket();
socket->setSocketDescriptor(socketDescriptor);
socket->moveToThread(this);
connect(socket, &QTcpSocket::readyRead, [this]() { qDebug() << socket->readAll(); }); //trying to read messages from clients
}
in Connection class: creating thread in incomingConnection()
void Connection::incomingConnection(qintptr socketDescriptor)
{
SocketThread *socketThread = new SocketThread(socketDescriptor);
socketThread->start();
connect(socketThread, &SocketThread::started, [&]() { socketThread->socket->write("Hello!"); }); //write a message to client when thread is created
}
Strange thing is, if I add this line:
connect(socketThread, &SocketThread::started, & { socketThread->socket->write("Hello!"); }); //write a message to client when thread is created
Then the socket will not read message from client. If I remove that line, the socket will read message from client.
I want the server to send message to client when a thread is created and to read message from client as well. How can do solve the problem?
Edit:
SocketThread header file:
class SocketThread : public QThread
{
Q_OBJECT
public:
SocketThread(qintptr descriptor, QObject *parent = 0);
~SocketThread();
QTcpSocket *socket;
qintptr socketDescriptor;
};
in the Connection constructor:
Connection::Connection(QObject *parent) : QTcpServer(parent)
{
this->listen(QHostAddress::Any, 6666);
}
And creating a connection object in the main.cpp file. That's really like all the code.
I am having trouble to connect a Signal to a Slot in the following code:
#include "myserver.h"
MyServer::MyServer(QObject *parent) :
QTcpServer(parent)
{
}
void MyServer::StartServer()
{
if(listen(QHostAddress::Any, 45451))
{
qDebug() << "Server: started";
emit servComando("Server: started");
}
else
{
qDebug() << "Server: not started!";
emit servComando("Server: not started!");
}
}
void MyServer::incomingConnection(int handle)
{
emit servComando("server: incoming connection, make a client...");
// at the incoming connection, make a client
MyClient *client = new MyClient(this);
client->SetSocket(handle);
//clientes.append(client);
//clientes << client;
connect(client, SIGNAL(cliComando(const QString&)),this, SLOT(servProcesarComando(const QString&)));
// para probar
emit client->cliComando("prueba");
}
void MyServer::servProcesarComando(const QString& texto)
{
emit servComando(texto);
}
The emit client->cliComando("prueba"); works, but the real "emits" don't.
The console does not show any connection error, and the QDebug texts shows everything works well.
Original code was copied from http://www.bogotobogo.com/cplusplus/sockets_server_client_QT.php
I found the problem, Im sending a signal BEFORE connecting:
client->SetSocket(handle);
sends the signal, and Im CONNECTing after it... Now it is:
// at the incoming connection, make a client
MyClient *client = new MyClient(this);
connect(client, SIGNAL(cliComando(const QString&)),this, SLOT(servProcesarComando(const QString&)));
client->SetSocket(handle);
And it works. I noticed it after read the following:
13. Put all connect statements before functions calls that may fire their signals, to ensure that the connections are made before the signals are fired. For example:
_myObj = new MyClass();
connect(_myObj, SIGNAL(somethingHappend()), SLOT(doSomething()));
_myObj->init();
not
_myObj = new MyClass();
_myObj->init();
connect(_myObj, SIGNAL(somethingHappend()), SLOT(doSomething()));
I found it at https://samdutton.wordpress.com/2008/10/03/debugging-signals-and-slots-in-qt/
Anyway, thanks for your answers!
I have a program that sends and receives broadcast messages. If I run two copies of these programs on the same PC, everything works just fine. If I run each copy on different PCs, then the broadcast messages are not received. I utilized Wireshark to verify whether the packets were sent (yes they were). In addition, on PC "A" Wireshark does not observe the sent packets, but on PC "B" everything is OK. Could the problem be in hardware?
Receiver code:
Receiver::Receiver(QObject *parent) : QObject(parent)
{
udpSocket = new QUdpSocket(this);
udpSocket->bind(45454, QUdpSocket::ShareAddress);
timer = new QTimer(this);
timer->start(500);
connect(timer, SIGNAL(timeout()), this, SLOT(processPendingDatagrams()));
}
void Receiver::processPendingDatagrams()
{
qDebug("first entrance");
while (udpSocket->hasPendingDatagrams()) {
QByteArray datagram;
datagram.resize(udpSocket->pendingDatagramSize());
udpSocket->readDatagram(datagram.data(), datagram.size());
qDebug() << datagram.data();
qDebug("Receive");
sendToQML(datagram.data());
}
}
Sender code:
Sender::Sender(QObject *parent) : QObject(parent)
{
messageNo = 0;
udpSocket = new QUdpSocket(this);
}
void Sender::broadcastDatagram(int message)
{
QByteArray datagram = QByteArray::number(message);
udpSocket->writeDatagram(datagram.data(), datagram.size(),
QHostAddress::Broadcast, 45454);
}
void Sender::sendBroadcast(int message)
{
qDebug() << message;
broadcastDatagram(message);
}
UPDATE
I managed to send and receive packets through an ethernet connection (via a cable).
There is an example from the official QT documentation of QUdpSocket datagrams reading:
void Server::initSocket()
{
udpSocket = new QUdpSocket(this);
udpSocket->bind(QHostAddress::LocalHost, 7755);
connect(udpSocket, SIGNAL(readyRead()),
this, SLOT(readPendingDatagrams()));
}
void Server::readPendingDatagrams()
{
while (udpSocket->hasPendingDatagrams()) {
QByteArray datagram;
datagram.resize(udpSocket->pendingDatagramSize());
QHostAddress sender;
quint16 senderPort;
udpSocket->readDatagram(datagram.data(), datagram.size(),
&sender, &senderPort);
processTheDatagram(datagram);
}
}
I'm trying to understand what exactly happens, when readyRead() signal emits. In the while loop (in Server::readPendingDatagrams() slot) we read available datagrams, but what happens if new datagram appends to the socket, while we still read the previous datagrams batch? readyRead() signal will be emited again? But how while loop will be read the data in this case - from last appended datagram or in some other way?
I have problem with QUdpSocket. I want to create a simple program to send and receive data using the UDP protokol. I already read many similar topic but I do not found solved. Communication worked only for QHostAdress::LocalHost, then I give this same data as send, but if I want to send data to outside set concrete address, for example 194.181.161.134, that does not worked. That mean data is send but I can't receive. This is my code:
class Okno_GL : public QMainWindow
{
Q_OBJECT
public:
explicit Okno_GL(QWidget *parent = 0);
QWidget *wg;
QPushButton *pb;
QPushButton *pl;
QGridLayout *gr;
QUdpSocket *socket;
QHostAddress host;
QHostAddress bcast;
signals:
public slots:
void SLOT_Write();
void SLOT_load();
};
class Receiver : public QObject
{
Q_OBJECT
public:
Receiver();
QUdpSocket *udpSocket;
public slots:
void SLOT_processPendingDatagrams();
void SLOT_StCh(QAbstractSocket::SocketState state);
};
Okno_GL::Okno_GL(QWidget *parent) :
QMainWindow(parent)
{
pb = new QPushButton("write" , this);
pl = new QPushButton("read" , this);
wg = new QWidget(this);
setCentralWidget(wg);
gr = new QGridLayout(wg);
gr->addWidget(pb);
gr->addWidget(pl);
socket = new QUdpSocket(this);
connect(pb , SIGNAL(clicked()) , SLOT(SLOT_Write()));
connect(pl , SIGNAL(clicked()) , SLOT(SLOT_load()));
}
void Okno_GL::SLOT_Write()
{
QByteArray datagram = "gS";
int send;
send = socket->writeDatagram(datagram.data(), QHostAddress("194.181.161.134"), 1200);
}
void Okno_GL::SLOT_load()
{
}
Receiver::Receiver()
{
udpSocket = new QUdpSocket(this);
connect(udpSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)) , this , SLOT(SLOT_StCh(QAbstractSocket::SocketState)));
if(udpSocket->bind(QHostAddress::Any , 1200))
{
qd "bind";
}
else
{
qd "not bind";
}
}
void Receiver::SLOT_processPendingDatagrams()
{
qd "receiver";
QByteArray datagram;
do {
datagram.resize(udpSocket->pendingDatagramSize());
udpSocket->readDatagram(datagram.data(), datagram.size());
} while (udpSocket->hasPendingDatagrams());
qd "datagram" << datagram;
}
void Receiver::SLOT_StCh(QAbstractSocket::SocketState state)
{
qd "slot" << state;
QByteArray datagram = "gS";
if ( state == QAbstractSocket::BoundState ) {
connect(udpSocket, SIGNAL(readyRead()), this, SLOT(SLOT_processPendingDatagrams()) , Qt::QueuedConnection);
}
}
You should use write() instead of writeDatagram()
qint64 QUdpSocket::writeDatagram(const char * data, qint64 size, const QHostAddress & address, quint16 port)
Warning: Calling this function on a connected UDP socket may result in
an error and no packet being sent. If you are using a connected
socket, use write() to send datagrams.
So, I rebuild my code accordingly with your proposition. I add this line in construktor class Okno_GL.
socket = new QUdpSocket(this);
socket->connectToHost(QHostAddress("194.181.161.134") , 1200);
Here is slot to send
void Okno_GL::SLOT_Write()
{
QByteArray datagram = "gS";
int send;
// send = socket->writeDatagram(datagram.data(), QHostAddress("194.181.161.134"), 1200);
send = socket->write(datagram);
qd " send" << send;
}
Receiver code is not change, so I still white for signal readRedy() ,and I do not get him after send data.
PS. I whant to add that I have other option to connetc, is very very simply file command *bat whitch connect this host without any problem . This is proof that my network or admin nothing blocks (port , ip);
Pss thanks for your interest
Problem solved ! It is very stupid mistake. I should be send 3 bajt instead 2. The 3 bajt it is 0x0D.
Following code is work
socket = new QUdpSocket(this);
socket->bind(QHostAddress::Any, 1200);
and send
QByteArray datagram = "gS";
datagram.append(0x0D);
int send;
send = socket->writeDatagram(datagram.data(), QHostAddress("194.181.161.134"), 1200);
and receive after signal readyRead()
qd "receiver";
QByteArray datagram;
do {
datagram.resize(socket->pendingDatagramSize());
socket->readDatagram(datagram.data(), datagram.size());
} while (socket->hasPendingDatagrams());
qd "datagram" << datagram;
very help mi wireshark. Thanks for all