我想通过命名管道发送数据块,并希望接收器知道数据块的结束位置。我应该如何使用命名管道?我应该使用某种格式来连接和拆分块(将管道总是作为字节流处理)还是有其他方法?
我尝试在发送方为每个数据块打开和关闭管道,但数据在接收方连接(EOF不发送):
for _ in range(2):
with open('myfifo', 'bw') as f:
f.write(b'+')
结果:
rsk@fe temp $ cat myfifo
++rsk@fe temp $
答案 0 :(得分:3)
您可以在管道上使用某种分隔符或框架结构,或者(最好)使用类似对象的multiprocessing.Pipe
并通过它们运行Pickled Python对象。
第一个选项是简单地定义一个将通过管道运行的简单协议。为您发送的每个数据块添加标题,以便您知道如何处理它。例如,使用长度值系统:
import struct
def send_data(file_descriptor, data):
length = struct.pack('>L', len(data))
packet = "%s%s" % (length, data)
file_descriptor.write(packet)
def read_data(file_descriptor):
binary_length = file_descriptor.read(4)
length = struct.unpack('>L', binary_length)[0]
data = ''
while len(data) < length:
data += file_descriptor.read(length - len(data))
至于另一个选项 - 您可以尝试阅读multiprocessing
模块的代码,但实际上,您只需通过管道运行cPickle.dumps
的结果,然后将其读入{{1}获取Python对象。
答案 1 :(得分:1)
我只会使用JSON ecoded数据行。这些都很容易调试,性能也很合理。
有关读写行的示例: http://www.tutorialspoint.com/python/file_writelines.htm
有关使用ujson(UltraJSON)的示例: https://pypi.python.org/pypi/ujson
答案 2 :(得分:1)
除了其他解决方案,您不需要坚持命名管道。命名套接字并不差,并提供更方便的功能。使用AF_LOCAL和SOCK_SEQPACKET,消息边界传输由内核维护,因此单个send()写入的内容将通过单个recv()获得。