PDA

View Full Version : Problems with QTcpServer



elcuco
13th March 2011, 21:36
I am trying to create an XML based protocol, using Qt4, and I am having problems. The problem is that only 2*n+1 connection from the client gets into the server. The client is ok (I think), since I recoded it in C# and found the same problem.

I am not sure why the server is "eating" some of the XML sent to it. Can anyone give me a hint? To debug this I used "nc -l" and I see that the client does send the correct data. When I use "nc" to emulate the client, I see that the server is not processing the datastream. The correct method is invoked but the XML is not read.



/////////////////////////////////////
// client code, parts of it at least
/////////////////////////////////////
MyClient::MyClient()
{
connection = new QTcpSocket(this);
}

void MyClient::connect( QString host, int port )
{
connection->connectToHost(host,port);
if (!connection->waitForConnected()){
qDebug("Aborting, no connection");
}
}

void MyClient::sendConnectionString(QString s)
{
QXmlStreamWriter w(connection);
// send some XML
}



/////////////////////////////////////
// this is the server
/////////////////////////////////////
MyServer::MyServer(QObject *parent): QObject(parent)
{
qDebug("Server started");
server = new QTcpServer(this);
connect(server, SIGNAL(newConnection()), this, SLOT(on_newConnection()));
}

void MyServer::start()
{
server->listen(QHostAddress::Any,2008);
qDebug("Started server");
}

void MyServer::on_newConnection()
{
QTcpSocket *s = server->nextPendingConnection();
connect(s,SIGNAL(readyRead()), this, SLOT(on_bytesArrived()));
connect(s,SIGNAL(disconnected()), this, SLOT(on_connectionClosed()));
qDebug("New connection from %s:%d", qPrintable(s->peerAddress().toString()), s->peerPort() );
}

void MyServer::on_connectionClosed()
{
QTcpSocket *s = qobject_cast<QTcpSocket*>(sender());
if ( s == NULL)
return;
qDebug("Connection from %s:%d closed", qPrintable(s->peerAddress().toString()), s->peerPort() );
}

void MyServer::on_bytesArrived()
{
qDebug("1111111"); // I do see this
QTcpSocket *s = qobject_cast<QTcpSocket*>(sender());
if ( s == NULL) {
qDebug("No socket");
return;
}

QDomDocument d;
d.setContent(s);
// I don't see this following line
qDebug("read\n%s", qPrintable(d.toString(4)));
}


PS: I do know I need to fix the code to use QSignalMapper. This will be done as soon as I find the problem here.

EDIT:
I see this thread, but I don't learn anything about my problem... Am I close...?
http://www.qtcentre.org/threads/19911-QTcpSocket-QTcpServer-problem
http://lists.trolltech.com/qt-interest/2006-03/thread01624-0.html

unit
13th March 2011, 22:05
I think your app receive more than one packet. So you should read all received data and than create QDomDocument.

elcuco
13th March 2011, 22:08
I know that. I another project I read a long, which means the amount of bytes to read, then I those bytes into the DomDocument.

This time I want to do it the right way, maybe using QXmlStreamReader. The problem - I *do* need the DOM. How can I do this?

unit
13th March 2011, 22:12
Read all and create QDomDocument or create class (that use or subclass QXmlStreamReader), that read data and create xml

Or find other solution

elcuco
13th March 2011, 22:27
Changing the code to



QString str = s->readAll();
QDomDocument d;
d.setContent(str);


Does seem to fix the problem, but for some reason I am not happy about it.

unit
14th March 2011, 08:26
QDomDocument can read from IODEVICE. But problem that QTcpSocket is stream device, so he should read all data (many readready signals), and after that he create QDomDocument

wysota
14th March 2011, 08:40
Read (append) all data to an additional buffer and try creating the dom tree out of that. Once QDomDocument::setContent() is successful, you know you received the full DOM tree. Then you just have to check how much of the data to discard from the buffer (there can be more data waiting in the buffer).

elcuco
15th March 2011, 20:32
How can I do this? by reading one byte at a time?
What happens if I read too much (and I have for example one full XML and part of the next one?)

wysota
15th March 2011, 21:17
How can I do this? by reading one byte at a time?
It's up to you to find a reasonable algorithm. You could try detecting the closure of the tag that was the first tag in the document.


What happens if I read too much (and I have for example one full XML and part of the next one?)
No idea. It will either work or fail, fake some small piece of xml and find out yourself.