【问题标题】:Communication fails between Python 3 socket and QTcpsocket (c++)Python 3 套接字和 QTcpsocket (c++) 之间的通信失败
【发布时间】:2018-01-09 00:51:11
【问题描述】:

目前使用 Qt 的 QTcpsocket 库和 python 3 的套接字类。我已经获得了 Qt 的 c++ 财富客户端/服务器示例来正确构建和运行。但是,它适用于都是 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() 返回 false。我最初的直觉是 python 端的编码是错误的。 QDataStream 是否需要特殊编码?

QDataStream::commitTransaction() 的文档:

bool QDataStream::commitTransaction()

完成一个读取事务。如果没有发生读取错误,则返回 true 交易期间;否则返回false

另外,运行后,这里是c++客户端的输出:

Connected to server...
Reading: 25
Read errors have occurred.

【问题讨论】:

    标签: c++ python-3.x sockets network-programming qtcpsocket


    【解决方案1】:

    当您想将QDataStream 与运算符&gt;&gt; 一起使用时,您必须遵循序列化格式。调用QDataStream.setVersion()选择具体格式。

    我只能找到version 12(适用于QDataStream::Qt_4_6QDataStream::Qt_4_9)和version 13QDataStream::Qt_5_0)的文档。

    版本 12 和 13 具有相同的 QString 序列化格式:

    > 如果字符串为空:0xFFFFFFFF (quint32)

    > 否则:以字节为单位的字符串长度 (quint32),后跟 UTF-16 格式的数据

    当您调用m_dataStream &gt;&gt; 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("&gt;I", len(msg)) - 创建一个 32 位无符号整数,包含大端序 (&gt;) 中编码字符串 (I) 的长度

    发送到 Qt 客户端的所有数据都是大端顺序,因为它是 QDataStream 使用的隐式顺序。

    我已经用 Qt 5.9 和序列化版本QDataStream::Qt_4_0 测试了代码。

    【讨论】:

    • 谢谢,是的,这使我能够正确接收客户端上的消息。非常感谢!
    猜你喜欢
    • 1970-01-01
    • 2012-01-26
    • 1970-01-01
    • 2016-10-29
    • 2012-06-07
    • 1970-01-01
    • 2011-10-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多