如何将字节从套接字切割成单独的片段

2024-06-16 08:25:37 发布

您现在位置:Python中文网/ 问答频道 /正文

好吧,标题可以用更好的措辞,但问题是

我正在快速地将数据发送到一个套接字,我需要将发送的每一条信息分开

例如:

import pickle
#Sending side
while True:
     data = pickle.dumps((listelement1, listelement2, listelement3)) #All list elements may change value
     conn.send(data)


import pickle
#Revieving side
while True:
     dataget = conn.recv(1024)
     data_arr = pickle.loads(dataget)
     print(data_arr)

这当然不是实际的代码,而是我最好的例子。我试图确保“dataget”始终是一个完整的“数据”,而不会意外地截断或切断数据的前端,我该怎么做


Tags: 数据import信息true标题dataconnside
1条回答
网友
1楼 · 发布于 2024-06-16 08:25:37

基本问题是,您需要某种方法来在TCP字节流中取消标记消息。这很快就会变得复杂。腌制过的溪流知道它们自己的大小,如果你计划做的只是来回传递腌制过的东西,你可以利用这些知识。假设您坚持使用阻塞I/O,那么在发送端它很简单,只需pickle和send,但是使用s.sendall()来确保它真正运行send()可能发送比您要求的少,您必须检查其返回并继续发送。sendall为你做的

接收端更复杂pickle.loads要求您首先加载字节字符串(您如何知道它有多长?),而不告诉您它消耗了多少流pickle.Unpickler执行您想要的操作,但使用的是文件对象,而不是套接字。如果继续阻止套接字,可以使用socket.makefile()为套接字创建一个文件对象,并将其与unpickler一起使用

下面是一个工作示例

import sys
import socket
import pickle

PORT = 8722

def client():
    s = socket.socket()
    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    s.connect(('localhost', PORT))
    f = s.makefile(mode='wb')
    pickle.dump(["list 1", 1,2,3], f)
    pickle.dump(["list 2", 4, 5, 6], f)
    pickle.dump(["list 3", 7, 8, 9], f)
    f.close()
    s.close()

def server():
    s = socket.socket()
    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    s.bind(('localhost', PORT))
    s.listen(1)
    conn, addr = s.accept()
    f = conn.makefile(mode='rb')
    unpkl = pickle.Unpickler(f)
    try:
        while True:
            obj = unpkl.load()
            print(obj)
    except EOFError:
        print('done')

try:
    if sys.argv[1] == "client":
        client()
    elif sys.argv[1] == "server":
        server()
    else:
        raise IndexError()
except IndexError:
    print("test.py client|server")
    exit(1)

或者,您可以实现一些方法来划分每个pickle缓冲区。可能是通过struct写入的包含大小的小头。然后这是一个两步的过程:读取标题,然后使用该大小读取数据。您甚至可以将其升级并使用其他方法,如HTTP rpc或zeromq等

相关问题 更多 >