2014-02-18 29 views
0

我正在學習Python中的套接字,並且我在一臺機器上編寫了一個簡短的服務器套接字程序,可以使用telnet xxx.xxx.xxx.xxx 8888進行輪詢。溝通工作正常,但由於某種原因,當我正在評估從客戶端發送的data時,它似乎沒有像應該那樣評估。使用if語句評估的Python套接字數據行爲意外

有問題的代碼如下:

data = conn.recv(1024) # receive data 
    conn.sendall(data)  # reply to confirm what data was received 
    if data == "green": 
      reply = 'GREEN ON' 
    elif data == "red": 
      reply = 'RED ON' 
    else: 
      reply = 'Command not recognized' 
    conn.sendall(reply) 

從客戶端我做到以下幾點:

telnet 192.168.0.8 8888 
Trying 192.168.0.8... 
Connected to 192.168.0.8. 
Escape character is '^]'. 
Welcome to the server. Type something and hit enter  # server responds with connection confirmation 
green   #typed from client 
green   #server responds with the data it received 
Command not recognized  #<-- data is not evaluated correctly in if statement 

所以發生的是我查詢使用telnet的服務器,它具有指示Welcome to the server...響應連接成功。然後我輸入​​,服務器用它收到的數據作出響應(即​​因此是同一行兩次),但隨後告訴我該命令未被識別,意味着服務器程序上的if語句沒有正確評估data

我是否缺少一些東西,比如數據實際上是空終止的,如green\0導致if塊中的錯誤評估?

回答

2

你大概是按照指示說的輸入內容並按Enter鍵。所以,你發送'green\n'。或者也許'green\r\n'

無論如何,'green\n' != 'green''green\r\n' != 'green'

一個很好的測試方法是打印出你得到的結果。打印一個字符串的repr會引用它並且轉義所有的控制字符,所以你會看到完全是'green\r\n'而不是僅僅是​​,後面跟着一個空行,這很容易解釋。 (這也可以讓你排除虛假\0終結者等)

你可以通過檢查,例如data.rstrip()而不是data來解決這個問題。

然而,一旦你這樣做,你的程序實際上不會工作,它會只是工作大部分時間,或在某些情況下(如在本地主機上測試)。這是一個難以捉摸的錯誤的祕訣,當你最終找到它們時,你需要重寫你的整個應用程序。

一個recv可以從三個不同的send小號得到一個send的數據,或者從send一半的數據,或者數據。如果你收到'gre''green\r\nbl',沒有任何操作會使它匹配'green'

要解決這個問題,您需要設計一個協議,以某種方式分隔消息,然後在recv上循環,添加到緩衝區並分離消息。或者,如果你的協議只是「用一個換行符終止每一個命令」(並且命令中沒有嵌入的換行符),你可以使用socket.makefile,它給你一個類似文件的對象,可以自動爲你做 - 所以你可以只需逐行迭代(或調用readline等)。),就像你可以使用普通文件一樣。你甚至可以用通用的換行支持打開它,所以你不必擔心討厭的矛盾\r\n\n

查看Sockets are byte streams, not message streams瞭解更多詳情。

+0

感謝您的回覆。我改變了那行代碼來讀取'if data =='green \ n「'但仍然是相同的。 – nagyben

+0

@exantas:放入一個'print(repr(data))'語句來查看你實際接收到的內容。我會是'\ r \ n'與'\ n'問題,但實際上,沒有理由繼續猜測。 – abarnert

+0

你說得對,它確實收到了'green \ r \ n'。這是一個很好的提示,謝謝! – nagyben

1

這裏的問題很可能是從telnet發送換行符。嘗試在if塊之前剝去尾部空白:

data = data.rstrip()