2017-08-10 59 views
0

我想在Python中編寫我的第一個客戶端服務器應用程序。我的客戶端向服務器端發送不同的命令。例如,其中之一是用於在命令shell中執行命令。它看起來像:如何從Python中分離接收到的數據?

client.send("execute".encode("utf-8")) 
client.send(command.encode("utf-8")) 

在服務器端,我想收到這樣說:

data = client.recv(BUFF_SIZE).decode("utf-8").strip() 
if data == "execute": 
    command = client.recv(BUFF_SIZE).decode("utf-8").strip() 
    ... 

,但我得到「執行{}命令」字符串「數據」變量,= =「執行」條件未滿足。我是客戶端 - 服務器應用程序的新手,不知道如何正確執行。我做錯了什麼?

if data.split("{")[0] == "execute" 

解釋:

data = "execute{command}" 
print data.split("{")[0] 

打印

"execute" 

由於數據是一個字符串,你

+0

@ 3D1T0R在這種情況下,我得到一個字符串「execute \ n {command}」,但仍然在同一個'data'變量中。 –

回答

0

,你可以通過改變服務器代碼的if語句來解決這個問題可以使用split方法將字符串拆分爲使用「{」字符的列表。

這樣:

data.split("{") 

將返回

["execute", "commmand}"] 

因爲你要 「執行」 你把索引0列表

+0

不,我的意思是,我想將這兩條消息分別接收到不同的變量中。而我的問題是,recv函數將兩個消息都放在一個'data'中。 –

+0

什麼是BUFF_SIZE設置爲? – AllenMoh

+0

它被設置爲1024字節 –

4

要認識到的一點是,TCP是一個字節流。您從TCP獲得的保證是您發送的字節將以相同的順序到達。如果字節流表示一系列命令,則不能保證字節將以與您發送的內容對齊的塊形式到達。 您可能會發送:「執行」,「命令」 並接收「e」「xecuteco」「mmand」。

(是的,這是非常不可能的,但由於nagle算法的緣故,接收「executecommand」的可能性很大,但我離題了一點,就是爲了編寫健壯的代碼,你的數據分成小塊)

因此,你需要決定的第一件事情是請求字節流如何分割成請求,以及響應字節流如何分割成響應。在請求內部,您需要確定其內部結構。

假設你決定該請求看起來像: 「動詞參數1參數2 ...... paramN \ n」個 即:

  1. 請求是不換行字節序列,然後是換行符
  2. 該請求是由一個初始動詞(非空格字符),接着是零個或多個參數

由於協議本身現在有超過TCP的附加層,則最好使用abstracti來編碼這上。一些類似於:

class Request(object): 
    def __init__(self, verb, *args): 
     self.verb = verb 
     self.args = [str(x) for x in args] 

class Client(object): 
    def __init__(self, sock): 
     self.sock = sock 
     self.rxbuf = '' 

    def send_request(self, req): 
     req_str = req.verb 
     if req.args: 
      req_str += ' ' + ' '.join(req.args) 
     req_str += '\n' 
     self.sock.sendall(req_str.encode("utf-8")) 

class Server(object): 
    def __init__(self, sock): 
     self.sock = sock 
     self.rxbuf = '' 
    def read_request(self): 
     while True: 
      s = self.rxbuf.split('\n', 1) 
      if len(s) == 2: 
       req_str = s[0] 
       self.rxbuf = s[1] 
       req_lst = req_str.split(' ') 
       return Request(req_lst[0], *req_lst[1:]) 
      data = self.sock.recv(BUF_SIZE).decode("utf-8") 
      self.rxbuf += data 

當然,這必須通過的回答將如何看起來像,以及如何將輸入的字節流描繪成響應序列的決定的補充。我試圖讓這段代碼的主要觀點是,

  1. 你讀取的字節
  2. 你積累他們
  3. 嘗試看看,如果到目前爲止,你已經得到了的東西是一個完整的請求
  4. 如果是的話 - 分析,並將其餘的下一次

這假設請求相當小,你不必流它們,這是一個更高級的話題。

+0

非常感謝!我發現你是一個有知識的人,你能幫助或指導我解決更多問題嗎?爲了客戶端和服務器,雙方必須打開必要的端口。除了手動打開它,沒有更多的解決方案? –

相關問題