Qt: Python tcp client sends data over socket. How to read these bytes with Qt?
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 cli开发者_如何学Cent 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 :)
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.
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:
- Read a
quint16
, if there aren't enough bytes to be read, wait for more. quint16
read, wait until we have atleast the amount of thequint16
to be read.- 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.
精彩评论