的是,你需要在決定至少兩個問題:
- 如何交換信息?
- 以什麼格式?
關於1. TCP套接字是最低級別,您需要處理低級別的事情,如識別消息邊界。此外,只有連接沒有重置(由於例如臨時網絡故障),TCP連接才能爲您提供可靠的傳輸。如果希望應用程序在TCP連接重置時正常恢復,則需要實現某種形式的消息確認以跟蹤需要通過新連接重新發送的內容。 OMQ爲您提供比純TCP連接更高的抽象級別。你不需要處理一個字節流,而是處理整個消息。它仍然不能給你可靠的交付,消息可能會丟失,但它提供了幾種可用於確保可靠交付的通信模式。 0MQ也是高性能的,IMO是個不錯的選擇。
關於2,如果不需要與其他語言的互操作性,Pickle是一個非常方便和Pythonic的選擇。如果需要互操作性,可以考慮使用JSON,或者如果性能問題,則可以使用二進制格式,例如Google協議緩衝區。最後的選擇需要最多的工作(你需要在.idl文件中定義消息格式),這絕對不會感覺到Pythonic。
看看消息的交換(任何可序列化Python對象)在一個普通的插座怎麼能是這樣的:
def send(sockfd, message):
string_message = cPickle.dumps(message)
write_int(sockfd, len(string_message))
write(sockfd, string_message)
def write_int(sockfd, integer):
integer_buf = struct.pack('>i', integer)
write(sockfd, integer_buf)
def write(sockfd, data):
data_len = len(data)
offset = 0
while offset != data_len:
offset += sockfd.send(data[offset:])
不壞,但你可以看到有處理消息長度的序列化相當低的水平。
,並接收這樣的消息:
def receive(self):
message_size = read_int(self.sockfd)
if message_size == None:
return None
data = read(self.sockfd, message_size)
if data == None:
return None
message = cPickle.loads(data)
return message
def read_int(sockfd):
int_size = struct.calcsize('>i')
intbuf = read(sockfd, int_size)
if intbuf == None:
return None
return struct.unpack('>i', intbuf)[0]
def read(sockfd, size):
data = ""
while len(data) != size:
newdata = sockfd.recv(size - len(data))
if len(newdata) == 0:
return None
data = data + newdata
return data
但這並不優雅地處理錯誤(不嘗試確定哪些郵件已成功交付)。
其實,0mq確實給你可靠的交付,如果你使用一個代理(如RabbitMQ的),它支持。 –
有一個二進制JSONish格式(明顯是BSON:-P),它是跨語言的(例如由MongoDB使用),並且是靈活性(protobufs不給你的)和解碼速度(JSON是合理的不好)。 –