用python中的套接字在文件之前发送元数据

2024-10-01 09:40:29 发布

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

我正在努力使用套接字实现一些“精确”的数据交换。我有一个程序可以使用这些套接字发送/接收文件,我已经准备好在第一阶段发送文件名和文件大小。你知道吗

一切似乎都很好,但有时收到的数据不是预期的数据。我猜接收到的数据是同时到达的两个Tx“发送操作”的数据,因此我对接收到的字符串的预期“解析”不正确,它崩溃了。你知道吗

目前我的代码对于接收器是这样的:

 while True:
    c, addr = self.s.accept()
    l = c.recv(1024)
    while (l):
        if stage < 2:
            self.__recvHeader(l)
            stage += 1
        else:
            self.f.write(l)
        l = c.recv(1024)

作为__recvHeader函数:

def __recvHeader(self, data):
    line = data.decode("utf-8").split(":")
    if line[0] == "Name":
        self.filename = line[1]
        self.f = open("/tmp/" + self.filename, 'wb')
    elif line[0] == "Size":
        self.size = int(line[1])
    else:
        print("ERROR: " + "".join(line))

Tx的作用是:

# Here I send some headers first, then
l = f.read(1024)
while (l):
    self.s.send(l)
    l = f.read(1024)

sendHeader函数为:

def __sendHeader(self, name, value):
    self.s.send((name + ":" + value).encode('utf-8'))

对我来说,这个问题似乎是我不能为头设置一个固定的长度,因为文件名和文件大小可能会改变。你知道吗

你知道如何处理这个问题吗?或者我如何将这些数据转换成固定大小的数据来避免这个问题?最后一个选项也需要一个不同的“解析”IMO,不是吗?你知道吗


Tags: 数据函数selfsenddataif文件名def
2条回答

我假设您使用的是TCP/IP套接字。TCP/IP是一种流协议,对您的数据结构一无所知。如果您在一次send()操作中发送“消息”,则不能保证它会在一次recv()操作中到达。或者一个recv()操作将只接收一条“消息”。在您的例子中,头是一条消息。你知道吗

因此,您必须以某种方式对消息进行分隔,以便接收方能够正确地接收和解析它们。基本上有两种选择:

  1. 首先发送头的长度(字节数),然后发送头数据。接收器首先读取长度,然后读取那么多字节。你知道吗
  2. 在每个标头后发送分隔符。接收器读取报头数据,直到收到分隔符。你知道吗

在第一个选项中,您必须考虑如何发送长度。如果使用多字节值,例如32位值,则可能需要在发送之前将其转换为网络字节顺序。见htonl。你知道吗

在第二个选项中,您可以逐字节recv(),但这将非常缓慢。您可能需要使用某种缓冲。你知道吗

确保您使用的套接字为:socket.SOCK_STREAM!这意味着套接字使用TCP,它确保您的数据按顺序到达(在合理的“保证”范围内)。如果问题仍然存在,请继续阅读。。。你知道吗

我将首先base64对您的文件进行编码,以消除数据中的任何奇怪之处。base64使用limited alphabet对数据进行编码。因此,添加一个不在该字母表中的标记符号既简单又安全。您可以直接执行(伪代码):

while ('$'.encode('utf-8') not in l):
    l = c.recv(1024)
    # append l to a bytearray or similar

你只要发送"$<base64filecontent>$"。你知道吗

相关问题 更多 >