2017-08-02 199 views
0

當前使用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. 

回答

0

當你想使用QDataStream與運營商>>你必須遵循一個序列化格式。撥打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 >> 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測試了代碼。

+0

謝謝是的,這使我能夠在客戶端正確接收消息。非常感謝你! – user3701175