Python 3套接字和QTcpsocket之间的通信失败(C++)
当前使用Qt的QTcpsocket库和python 3的套接字类。我已经获得了Qt的C++ fortune客户端/服务器示例来构建和正确运行。但是,它适用于C++的客户端和服务器。要求是服务器正在运行Python。Python 3套接字和QTcpsocket之间的通信失败(C++)
# 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()
返回false。我最初的直觉是,python方面的编码是错误的。 QDataStream是否需要特殊编码?
的文档QDataStream :: commitTransaction():
布尔QDataStream :: commitTransaction()
完成读取事务。如果在交易过程中没有发生读取错误 ,则返回
true
;否则返回false
。
此外,运行程序后,这里是C的输出++客户端:
Connected to server...
Reading: 25
Read errors have occurred.
当你想使用QDataStream
与运营商>>
你必须遵循一个序列化格式。拨打QDataStream.setVersion()
选择具体格式。
我已经能够找到的记录仅version 12(从应用到QDataStream::Qt_4_6
QDataStream::Qt_4_9
)和version 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客户端的所有数据均采用big-endian顺序,因为它是QDataStream
使用的隐式顺序。
我用Qt 5.9和序列号版本QDataStream::Qt_4_0
测试了代码。
谢谢是的,这使我能够在客户端正确接收消息。非常感谢你! – user3701175