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

时间:2019-01-09 11:58:36

标签: python sockets

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

一切似乎都正常,但是有时接收到的数据不是预期的。我的猜测是,接收到的数据是同时到达的两个Tx“发送操作”的数据,因此我原本打算对接收到的字符串进行“解析”是不正确的,并且崩溃了。

当前,我的代码如下所示:接收器

class Agent < ApplicationRecord
    has_many :companies
end

成为 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

Tx 的功能如下:

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))

sendHeader 函数为:

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

我的问题似乎是我无法为标头设置固定长度,因为文件名和文件大小可能会更改。

关于如何处理此问题的任何想法,或者如何将这些数据转换为固定大小以避免出现此问题?最后一个选项也需要一个不同的“解析” IMO,不是吗?

2 个答案:

答案 0 :(得分:0)

我假设您正在使用TCP / IP套接字。 TCP / IP是一种流协议,对您的数据结构一无所知。如果在一项send()操作中发送了“消息”,则不能保证它将在一项recv()操作中到达。否则recv()操作将只收到一个“消息”。就您而言,标题就是一条消息。

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

  1. 首先发送标头的长度(字节数),然后发送标头数据。接收器首先读取长度,然后读取那么多字节。
  2. 在每个标头之后发送定界符。接收器读取标题数据,直到接收到定界符为止。

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

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

答案 1 :(得分:0)

确保您使用的套接字带有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>$"