2013-07-15 19 views
2

下面是一個簡單的Python 3.x的TCP服務器:查找消息中發送/接收的特定字節數。 (蟒蛇)

import socketserver 

class MyTCPHandler(socketserver.BaseRequestHandler): 

    def handle(self): 
     self.data = self.request.recv(1024).strip() 
     print(str(self.client_address[0]) + " wrote: " + str(self.data.decode())) 

if __name__ == "__main__": 
    HOST, PORT = "localhost", 9999 

    server = socketserver.TCPServer((HOST, PORT), MyTCPHandler) 
    server.serve_forever() 

和客戶端:

import socket 
import sys 

HOST, PORT = "localhost", 9999 

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
sock.connect((HOST, PORT)) 

while(True): 
    data = input("Msg: ") 

    if data == "exit()": 
     print("Exiting...") 
     sock.close() 
     exit(); 

    sock.sendall(bytes(data, "utf-8")) 

#numBytes = ....? 
#print("Sent: " + str(numBytes) + " bytes\n") 

我無法弄清楚如何查看字節的確切數字,我在發一個消息。我可以使用len(data),但是它沒有考慮空終止符,並且這樣......是否也發送了空終止符,或者它是不相關的?我試圖研究發送/接收消息的確切字節數,但是我找不到任何python特定的文檔,只能看到使用len()的人的例子,我認爲這不是確切的...

有沒有想法?

回答

4

Python字符串中沒有空終止符。如果你想發送一個,你必須明確地做到這一點:sock.sendall(bytes(data, "utf-8") + b'\0')

但是,除非您打算將它用作消息之間​​的分隔符,否則沒有充分的理由首先添加空終止符。 (請注意,這對於一般Python字符串不起作用,因爲它們允許在中間包含空字節......但它對於真正的人類可讀文本當然可以正常工作。)

將空字節用作分隔符不是一個壞主意......但你現有的代碼需要實際處理它。你不能只打電話recv(1024),並認爲這是一個完整的信息;你必須繼續調用recv(1024)進入一個循環,並追加到緩衝區中,直到找到null爲止,然後在循環中下一次保存null。


反正sendall方法不返回發送的字節數,因爲它總是發送正是你給它字節(除非有一個錯誤,在這種情況下,是提高)。所以:

buf = bytes(data, "utf-8") + b'\0' 
sock.sendall(buf) 
bytes_sent = len(buf) 

而在服務器端,你可能會想要寫一個NullTerminatedHandler類是這樣的:

class NullTerminatedHandler(socketserver.BaseRequestHandler): 
    def __init__(self): 
     self.buf = b'' 
    def handle(self): 
     self.buf += self.request.recv(1024) 
     messages = self.buf.split(b'\0') 
     for message in messages[:-1]: 
      self.handle_message(message) 
     self.buf = self.buf[:-1] 

然後你可以使用它像這樣:

class MyTCPHandler(NullTerminatedHandler): 
    def handle_message(self, message): 
     print(str(self.client_address[0]) + " wrote: " + str(message.decode())) 

雖然我們在這裏,但你有一些Unicode /字符串的問題。從最嚴重到最低:

  • 你應該幾乎永遠不會只是打電話decode沒有參數。如果您在一邊發送UTF-8數據,則一定明確地使用decode('utf-8')
  • decode方法保證會返回str,所以編寫str(message.decode())只會讓您的代碼感到困惑。
  • 示例代碼使用format而不是在一堆對象上調用str並將它們連接起來有一個原因 - 它通常比較容易閱讀。
  • 它通常比bytes(data, 'utf-8')更易於說data.encode('utf-8')
+0

嗯,所以在python的角度來看,len(buf),沒有添加空終止符,它是一個字節大小的準確度量? –

+1

@Noobacode:是的,如果你發送一個名爲'buf'的字節而不添加空終止符,'len(buf)'是緩衝區的長度。如果出於某種原因明確添加空終止符,那麼len(buf + b'\ 0')是具有空終止符的緩存長度。 – abarnert

+1

@Noobacode:請記住,這是以字節爲單位的長度,而不是字符的長度。如果你想要_that_,在將's'編碼爲UTF-8之前使用'len(s)'。 – abarnert