如何使用python套接字模块解码QTcpServer发送的QByteArray?



请考虑以下代码:

client.py

import socket
import json
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
s.connect(('127.0.0.1', 8000))
s.send(json.dumps({'text': 'hello world'}).encode("utf-8"))
data = s.recv(1024)
s.close()
print("received data:", data)
except Exception as e:
print("-->", e)

server.py

import sys
import json
from PyQt5.Qt import *  # noqa

class Server(QDialog):
def __init__(self):
super().__init__()
self.tcp_server = None
def run(self):
self.tcp_server = QTcpServer(self)
if not self.tcp_server.listen(QHostAddress('127.0.0.1'), 8000):
print("Can't listen!")
self.close()
return
self.tcp_server.newConnection.connect(self.on_new_connection)
def on_new_connection(self):
client_connection = self.tcp_server.nextPendingConnection()
client_connection.waitForReadyRead()
message_dct = json.loads(
client_connection.readAll().data().decode("utf-8"))
print("received json:", message_dct)
block = QByteArray()
out = QDataStream(block, QIODevice.ReadWrite)
out.writeString(json.dumps({'response': len(message_dct["text"])}).encode("utf-8"))
client_connection.disconnected.connect(client_connection.deleteLater)
client_connection.write(block)
client_connection.disconnectFromHost()

if __name__ == '__main__':
app = QApplication(sys.argv)
server = Server()
server.run()
sys.exit(server.exec_())

运行 server.py 并 client.py 后,client.py 将打印:

received data: b'x00x00x00x11{"response": 11}x00'

我不明白字典周围的额外字节(x00x00x00x11开头的 4 个字节(和最后一个字节(x00(是什么意思,它们是否代表 QTcpServer 添加的 TCP 元数据信息?

无论如何,我想知道在 client.py 上解码字典的正确方法是什么,这样你就可以得到字典{"response": 11}

NS:client.py 旨在运行在python3.3.6 python进程上,最简单的方法是使用标准库(即:使用扭曲或外部deps很棘手(,也...异步不可用... 这就是我使用旧的socket模块的原因。

QDataStream是一个负责序列化和实现各种类型的数据的类,因此它需要发送额外的信息,例如信息的大小。

转到您的消息:

json.dumps({'response': len(message_dct["text"])})

{"response": 11}

这是一个字符串,您可以使用encode("utf-8")将其转换为字节,显示字符0x00指示字符的结尾:

0x7B 0x22 0x72 0x65 0x73 0x70 0x6F 0x6E 0x73 0x65 0x22 0x3A 0x20 0x31 0x31 0x7D 0x00

因此,信息的长度为17个字节,十六进制为0x11

QDataStream发送数据时,数据的大小将用 4 个字节表示,因此我们观察到前 4 个字节在数字上为 11:

b'x00x00x00x11{"response": 11}x00'
[     length     ][       data       ]

对于上述内容,我们已经了解了该行为。

所以有2个解决方案:

  1. 在客户端使用QDataStream解码数据,但正如您指出的那样,您可以使用的包有限制。

  2. 不使用QDataStream并直接发送字节。

    def on_new_connection(self):
    client_connection = self.tcp_server.nextPendingConnection()
    client_connection.waitForReadyRead()
    message_dct = json.loads(
    client_connection.readAll().data().decode("utf-8"))
    print("received json:", message_dct)
    block = json.dumps({'response': len(message_dct["text"])}).encode("utf-8")
    client_connection.disconnected.connect(client_connection.deleteLater)
    client_connection.write(block)
    client_connection.disconnectFromHost()
    

最新更新