我正在努力使用套接字实现一些“精确”的数据交换。我有一个程序可以使用这些套接字发送/接收文件,并且我已经准备好在第一阶段发送文件名和文件大小。>
一切似乎都正常,但是有时接收到的数据不是预期的。我的猜测是,接收到的数据是同时到达的两个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,不是吗?
答案 0 :(得分:0)
我假设您正在使用TCP / IP套接字。 TCP / IP是一种流协议,对您的数据结构一无所知。如果在一项send()
操作中发送了“消息”,则不能保证它将在一项recv()
操作中到达。否则recv()
操作将只收到一个“消息”。就您而言,标题就是一条消息。
因此,您必须以某种方式分隔消息,以便接收者可以正确接收和解析它们。您基本上有两种选择:
在第一个选项中,您必须考虑如何发送长度。如果您使用多字节值(例如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>$"
。