簡體   English   中英

最簡單的python網絡消息傳遞

[英]Simplest python network messaging

我有一個Python的機器控制系統,目前看起來大致如此

goal = GoalState()
while True:
    current = get_current_state()
    move_toward_goal(current,goal)

現在,我正試圖增加通過網絡控制機器的能力。 我想寫的代碼是這樣的:

goal = GoalState()
while True:
    if message_over_network():
        goal = new_goal_from_message()
    current = get_current_state()
    move_toward_goal(current,goal)

將這種網絡功能添加到我的應用程序中最簡單,最Pythonic的方法是什么? 套接字可以工作,認為他們並不特別感覺Pythonic。 我看過XMLRPC和Twisted,但兩者似乎都需要對代碼進行重大修改。 我也看過ØMQ,但感覺我正在添加一個外部依賴項,它沒有提供任何我沒有使用套接字的東西。

我並不反對使用我上面提到的任何系統,因為我認為失敗可能是我的誤解。 我只是好奇地處理這個簡單,常見的問題的慣用方法。

至少有兩個問題你需要決定:

  1. 如何交換消息?
  2. 用什么格式?

關於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

但這並沒有優雅地處理錯誤(沒有嘗試確定哪些消息成功傳遞)。

如果您熟悉套接字,我會考慮使用SocketServer.UDPServer (請參閱http://docs.python.org/library/socketserver.html#socketserver-udpserver-example )。 UDP絕對是最簡單的消息傳遞系統,但顯然,您必須處理某些消息可能丟失,重復或無序傳遞的事實。 如果您的協議非常簡單,那么它的處理起來相對容易。 優點是您不需要任何其他線程,也不需要外部依賴項。 如果您的應用程序沒有會話概念,它也可能是非常好的選擇。

一開始可能會有好處,但還有更多細節需要考慮,不包括在你的問題中。 我也不會擔心插座不是非常Pythonic的事實。 無論如何,你最終會使用套接字,有人會為你包裝它們,你將被迫學習框架,在最好的情況下可能會滿足你的要求。

(請注意我的觀點非常偏頗,因為我喜歡處理原始套接字。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM