views:

673

answers:

2

Situation: I have tcp client made with Python and tcp server made with Qt. I try to send bytes with my client but I can't get Qt server to read these bytes.

Using Python made client and server, everything works fine. Also I can get my Python client work with C# server with no problems.

Code for Python client:

import socket
import sys

HOST = 'localhost'
PORT = 50505

try:
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except socket.error as msg:
    sys.stderr.write("[ERROR] %s\n" % msg)
    sys.exit(1)

try:
    sock.connect((HOST, PORT))
except socket.error as msg: 
    sys.stderr.write("[ERROR] %s\n" % msg)
    sys.exit(2)

sock.send(b'Hello World!\r\n')

I have tried e.q fortuneserver/fortuneclient code examples but they didn't work. Bytesavailable() is always 0.

So the question is how can I read in my Qt application that "Hello World!" line ? I just need that function which starts when a server emits newConnection() signal.

connect(tcpServer, SIGNAL(newConnection()), this, SLOT(startRead()));

UPDATE:

Part of the code for Qt server:

void Server::startRead()
{
QDataStream in(tcpSocket);
in.setVersion(QDataStream::Qt_4_0);
QString ipAddress;

if (blockSize == 0) {
    if (tcpSocket->bytesAvailable() < (int)sizeof(quint16))
        return;
    in >> blockSize;
}

if (tcpSocket->bytesAvailable() < blockSize)
    return;

QString nextFortune;
in >> nextFortune;

statusLabel->setText(nextFortune);

    ABOVE IS FROM FORTUNE CLIENT EXAMPLE. 

    BELOW IS FROM ANOTHER EXAMPLE.
/*
char buffer[128] = {0};
QTcpSocket *client = tcpServer->nextPendingConnection();
qDebug() << client->bytesAvailable();
for (int i=0; i<100; i++)
{
    client->read(buffer, client->bytesAvailable());
    qDebug() << buffer;
    std::string sString(buffer);
    QString qString(sString.c_str());
    statusLabel->setText(qString);
}
    */
}

That last part is rather bad. I tried to make something but I have no clue what I'm doing with Qt :)

A: 

The server code you attached works this way: Every 'packet' (logical one) is consisted of a size field, and following that size worth of data.

Basically it goes like this:

  1. Read a quint16, if there aren't enough bytes to be read, wait for more.
  2. quint16 read, wait until we have atleast the amount of the quint16 to be read.
  3. Once we have enough, we can read in the data.

After we understood that, even if you write the packet length like the server expects, what you're trying to do still won't work. This is because the way the server reads the QString from the socket. The client is writing a raw python string, I'm guessing it's just writing a plain old ASCII to the socket. The server is using a QDataStream to read from the socket (this is the standard way to serialize in Qt). If you look at the implementation of QString's operator<< here, it's doing much more than reading an ASCII string.

If you can't change your server, change your client. You can see the implementation of the fortune client in the examples that come with PyQt.

Idan K
A: 

You need to arrange for your code to read when there is data available. From your description, there is not data available yet when startRead() runs.

I assume you called QTcpServer::nextPendingConnection to get your tcpSocket in startRead()? If not, you need to do so.

Just connect the readyRead signal from your tcpSocket or client to a doRead() slot, and check bytesAvailable() and read in that slot.

This slot will get called whenever new data arrives.

You might also be interested in the disconnected() signal from your TCP socket to know when it is done sending data.

Jamey Hicks