Сбой связи между сокетом Python 3 и QTcpsocket (C++)
Использование библиотеки Qt QTcpsocket и класса сокетов Python 3 в настоящее время. Я уже получил пример клиент / сервер Qt C++ fortune для правильной сборки и запуска. Тем не менее, это для клиента и сервера, которые оба C++. Требование заключается в том, что на сервере работает Python.
# Server.py
import socket
# ...
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(("localhost", 45000)
sock.listen(1) # queuing up 1 request for now.
(clientsocket, address) = sock.accept() # waits until client connects.
chunk = clientsocket.recv(1024).decode() # client is now connect
print(chunk) #prints out message from client
msg = "Hello from the server"
msg = str.encode(msg)
# send the message back to the client
clientsocket.sendall(msg)
а также
// Client.h
#ifndef CLIENT_H
#define CLIENT_H
#include <QObject>
#include <QtNetwork/QtNetwork>
class Client : public QObject {
Q_OBJECT
public:
Client();
QTcpSocket *m_socket;
QHostAddress m_serverAddr = QHostAddress("127.0.0.1");
quint16 m_serverPort = 45000;
private:
QDataStream m_dataStream;
void testConnect();
};
#endif
а также
// client.cpp
Client::Client() {
m_socket = new QTcpSocket(this);
m_dataStream.setDevice(m_socket);
m_dataStream.setVersion(QDataStream::Qt_4_0);
testConnect();
}
void Client::testConnect() {
m_socket->abort(); // if m_socket is not already connected, this does nothing
m_socket->connectToHost(m_serverAddr, m_serverPort);
if (m_socket->waitForConnected(30000)) {
qDebug() << "Connected to server...";
m_socket->write("Hello server from client"); // is received!
m_socket->waitForBytesWritten();
m_socket->waitForReadyRead();
qDebug() << "Reading: " << m_socket->bytesAvailable();
m_dataStream.startTransaction();
QString nextFortune;
m_dataStream >> nextFortune;
if (!m_dataStream.commitTransaction()) {
qDebug() << "Read errors have occurred."; // prints when connected to python server. not desired behavior
m_socket->close();
return;
}
// This prints when running the Qt fortune c++ server, but not the python server (above).
qDebug() << "No read errors occurred during read transactions.";
qDebug() << nextFortune;
}
}
В итоге сервер получает сообщение от клиента без проблем, но когда сервер пытается отправить ответ с clientsocket.sendall(msg)
, m_dataStream.commitTransaction()
возвращает ложь Мой первоначальный инстинкт был в том, что кодировка была неправильной на стороне Python. Требуется ли для QDataStream специальная кодировка?
Документация для QDataStream:: commitTransaction ():
bool QDataStream:: commitTransaction ()
Завершает транзакцию чтения. Возвращает
true
если во время транзакции не было ошибок чтения; в противном случае возвращаетсяfalse
,
Кроме того, после запуска вот вывод клиента C++:
Connected to server...
Reading: 25
Read errors have occurred.
1 ответ
Когда вы хотите использовать QDataStream
с оператором >>
Вы должны следовать формату сериализации. Вызов QDataStream.setVersion()
выберите конкретный формат.
Я смог найти документацию только для версии 12 (применяется с QDataStream::Qt_4_6
в QDataStream::Qt_4_9
) и версия 13 (QDataStream::Qt_5_0
).
Версии 12 и 13 имеют одинаковый формат для сериализации QString:
> Если строка нулевая: 0xFFFFFFFF (quint32)
> В противном случае: длина строки в байтах (quint32), за которой следуют данные в UTF-16
Когда вы звоните m_dataStream >> nextFortune
он ожидает, что входящие данные будут в формате, описанном выше.
Код в Python для отправки закодирован QString
может выглядеть так:
import struct
msg = "Hello from the server".encode("utf-16be")
clientsocket.sendall(struct.pack(">I", len(msg)) + msg)
str.encode("utf-16be")
- кодирует строку в UTF-16 с порядком байтовstruct.pack(">I", len(msg))
- создает 32-разрядное целое число без знака, содержащее длину закодированной строки (I
) в порядке с прямым порядком байтов (>
)
Все данные, отправляемые клиенту Qt, находятся в порядке с прямым порядком байтов, потому что это неявный порядок, который QDataStream
использует.
Я протестировал код с Qt 5.9 и версией сериализации QDataStream::Qt_4_0
,