Python 3套接字和QTcpsocket之间的通信失败(c ++)

时间:2017-08-02 01:15:21

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

目前使用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()返回false。我最初的直觉是python方面的编码错误。 QDataStream需要特殊编码吗?

QDataStream的文档:: commitTransaction():

  

bool QDataStream :: commitTransaction()

     

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

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

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

1 个答案:

答案 0 :(得分:0)

如果要将QDataStream与运算符>>一起使用,则必须遵循序列化格式。调用QDataStream.setVersion()选择具体格式。

我之前只能找到version 12的文档(适用于QDataStream::Qt_4_6QDataStream::Qt_4_9)和version 13QDataStream::Qt_5_0)。< / p>

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

  

&GT;如果字符串为null:0xFFFFFFFF(quint32)

     

&GT;否则:字符串长度(以字节为单位)(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") - 使用big-endian顺序将字符串编码为UTF-16
  • struct.pack(">I", len(msg)) - 创建一个32位无符号整数,包含big-endian orderd(I
  • 中编码字符串(>)的长度

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

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