PDA

View Full Version : Problem with a UDP connection between two programs



fraubrj
27th December 2008, 10:07
I have two programs, A and B, who communicate by an UDP connection. They can beings on the same computer or two computers on a network.
The A program sends a command to the B program, which processes this command and sends then an answer to the A program.
Originally both programs were written in C# (WinXP). The A program was rewritten with Qt/C++, and it works well with the C# version of B (WinXP).
But I don't manage to put on the UDP connection with a Qt/C++ version of B.
Part of the A program

class radioInterfaceThread : public QThread
{
Q_OBJECT

QUdpSocket *udpCommandSocket;

public:
radioInterfaceThread(QObject *parent = 0);
~radioInterfaceThread();
void setConnectUDP();
protected:
void run();
private slots:
void udpRxEvent();
void sendCommand();
};


radioInterfaceThread::radioInterfaceThread(QObject *parent)
: QThread(parent)
, udpCommandSocket(0)
{
udpCommandSocket = new QUdpSocket;
connect(udpCommandSocket, SIGNAL(readyRead()), this, SLOT(udpRxEvent()), Qt::DirectConnection);
}

void radioInterfaceThread::run()
{
....
exec();
....
}


void radioInterfaceThread::setConnectTCP(QString addr, quint16 port)
{
udpCommandSocket->connectToHost(QHostAddress(addr), port, QAbstractSocket::ReadWrite);
}


void radioInterfaceThread::udpRxEvent()
{
qint64 bytes_available = 0;

while ((bytes_available = udpCommandSocket->bytesAvailable()) > 0)
{
QByteArray datagram;
datagram.resize(bytes_available);

qint64 bytes_read = udpCommandSocket->readDatagram(datagram.data(), datagram.size());
//... process the answer
}
}

// slot called to send Command
void radioInterfaceThread::sendCommand(QString cmd)
{
qint64 bytes_sent = 0;

//...
bytes_sent = udpCommandSocket->write(QString(cmd.trimmed() + "\r\n").toLatin1().constData());
//...
}

caduel
27th December 2008, 12:30
Iirc, you should not declare signals/slots in a QThread subclass. (Those won't be executed in the thread's context!)

On the other hand, I fail to see what the thread is for at all: signals/slots are asynchronous by nature, so a regular QObject-subclass (instead of the thread should work!)

Are you calling setConnectUDP() somewhere? Do you wait for the connection to be established before you start sending?

fraubrj
27th December 2008, 12:46
Iirc, you should not declare signals/slots in a QThread subclass. (Those won't be executed in the thread's context!)

On the other hand, I fail to see what the thread is for at all: signals/slots are asynchronous by nature, so a regular QObject-subclass (instead of the thread should work!)

Are you calling setConnectUDP() somewhere? Do you wait for the connection to be established before you start sending?
I have created a little A program with a GUI and a "Send" button. The setConnectUDP() call is made in the Constructor of the windows's GUI. A click on the "send" button call the "sendCommand" slot, so no problem of wait!

Remember, this A program work fine with C# B program!

I also tried with a version without thread, with the same result.

caduel
27th December 2008, 17:09
Maybe the problem is with your "B" program, then?
(If you strip down the program(s)) and provide us compilable (ideallly minimal examples) we are better able to help without guessing what you are doing :-)

fraubrj
27th December 2008, 20:21
The B program need an hardware board (it's the "Server" beetween the board and the GUI in a "Software Defined Radio" system)
So, no simple to give you a B compilable version!
But can be it's not necessary.
What I want to realize is that an A program sends (by an UDP connection) a request to the B program (that it is simple!) but after, the B program returns an answer to the A program. There, I found nothing of complete and functional. In the Qt's documentation, it is written :
If you want to use the standard QIODevice functions read(), readLine(), write(), etc., you must first connect the socket directly to a peer by calling connectToHost(). nothing more, and without real example! All that I tried does not work :(

caduel
27th December 2008, 20:53
a) You should separate the hardware dependent code from the network/server layer.
That way you can test the server part independently from the hardware part.

b) Have you tried the code at QUdpSocket? Does your "read-slot" get called? Ever?

fraubrj
27th December 2008, 22:44
OK, find attached files Test_A and Test_B in Test_A_B.zip
The slot " udpRxEvent() " of the program A is never called.

fraubrj
28th December 2008, 08:56
Here is the C# version of B program (without hardware dependent code)
You can verify that the program A (Qt) works perfectly with this program B (C#)

fraubrj
10th January 2009, 13:54
I finaly found solution :) all is on the run()



QTextStream out( stdout );

QUdpSocket m_socket;
QByteArray datagram;
QHostAddress sender;
quint16 senderPort;
QString in_qstr;
QString resp;

if (m_socket.bind(QHostAddress::Any, 55667) == -1) {
qDebug("Could not bind udp command_server socket...");
m_thread_go = false;
}
else
m_thread_go = true;

while (m_thread_go) {

if (m_socket.waitForReadyRead(100)) {
if (m_socket.hasPendingDatagrams()) {
datagram.resize(m_socket.pendingDatagramSize());
m_socket.readDatagram(datagram.data(), datagram.size(), &sender, &senderPort);
in_qstr = datagram.data();

resp = ProcessCommand(in_qstr.toLower());

datagram.clear();
datagram.append(resp);

if (m_socket.writeDatagram(datagram, sender, senderPort) == -1) {
qDebug("dropped at write");
m_socket.close();
return;
}
if (resp == "_exit_") {
m_socket.close();
m_thread_go = false;
emit exitCommand();
}
m_socket.flush();
}
}
}
m_socket.close();
}