在linux中通过命名管道发送数据块

时间:2013-12-21 14:06:25

标签: python linux file fifo

我想通过命名管道发送数据块,并希望接收器知道数据块的结束位置。我应该如何使用命名管道?我应该使用某种格式来连接和拆分块(将管道总是作为字节流处理)还是有其他方法?

我尝试在发送方为每个数据块打开和关闭管道,但数据在接收方连接(EOF不发送):

for _ in range(2):
     with open('myfifo', 'bw') as f:
         f.write(b'+')

结果:

rsk@fe temp $ cat myfifo 
++rsk@fe temp $

3 个答案:

答案 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()获得。