Python3.X Socket 一個編
- 2020 年 1 月 3 日
- 筆記
在看《Python核心編程》第三版 講述網絡編程Socket的知識,在練習中採用Python 3 的代碼中遇到一個與編碼解碼有關的坑,本文將給予詳細的介紹。
軟件環境
Python: 3.6.0 庫: socket
1. 問題初見
仿照書中的代碼(中文版 55-56頁) 加上自己的一點改動在我的環境中不能運行,總是報這個錯誤:TypeError: a bytes-like object is required, not 'str'
這裡是我的客戶端Socket代碼
from socket import * from time import ctime HOST = 'localhost' PORT = 10001 ADDRESS = (HOST, PORT) clientSocket = socket(AF_INET, SOCK_STREAM) clientSocket.connect(ADDRESS) while True: data = input('請輸入消息:') if not data: break clientSocket.send(data) data = clientSocket.recv(1024) if not data: break print("服務器返回的消息是:", data.decode('utf-8')) clientSocket.close()
我的環境是: Python 3.6.0, 怎麼破?
2. 研究錯誤 TypeError: a bytes-like object is required, not 'str'
錯誤的位置是在代碼clientSocket.send(data)部分,但是翻看python socket .send()源代碼_socket.py 方法說明
def send(self, data, flags=None): # real signature unknown; restored from __doc__
send(data[, flags]) -> count Send a data string to the socket. For the optional flags argument, see the Unix manual. Return the number of bytes sent; this may be less than len(data) if the network is busy. pass
這個send方法的參數期望的是一個 "a data string" 啊,而我確實給了一個string。
哪裡出問題了? 繼續查看官方文檔Socket,發現原因了。
官方對Socket的說明:
socket.send(bytes[, flags])
可以看到在Python 3中send()方法期望的是一個bytes, 而不是str 看來我我前面看到的是假的源代碼參數的說明。哈哈。
3. 用encode() 方法解決客戶端Socket 發送錯誤
解決錯誤的方法就是在調用send()方法之前對字符串類型數據進行encode,將字符串轉化成bytes 代碼如下:
clientSocket.send(data.encode())
與此同時,在服務端運行的時候也遇到了類似數據無法接收的問題。 如下代碼得到的data,是無法直接打印的。 data = clientSocket.recv(1024)
如果要打印data數據的話,也要調用decode()從而將數據從bytes轉化為str。
4. encode() 和 decode()
encode()編碼 : str -> bytes decode()解碼 : bytes -> str
默認的encoding是 utf-8
更多內容見官方文檔: str.encode() bytes.decode()
5. 完整Socket代碼
服務端:
from socket import * from time import ctime HOST = 'localhost' PORT = 10001 ADDRESS = (HOST, PORT) serverSocket = socket(AF_INET, SOCK_STREAM) serverSocket.bind(ADDRESS) serverSocket.listen(5) while True: print("等待客戶端連接...") clientSocket, address = serverSocket.accept() print(address, "已經成功連接至本服務器") while True: data = clientSocket.recv(1024) if not data: break replyMsg = data.decode() + "[" + ctime() + ']' clientSocket.send(replyMsg.encode()) clientSocket.close() serverSocket.close()
客戶端:
from socket import * from time import ctime HOST = 'localhost' PORT = 10001 ADDRESS = (HOST, PORT) clientSocket = socket(AF_INET, SOCK_STREAM) clientSocket.connect(ADDRESS) while True: data = input('請輸入消息:') if not data: break clientSocket.send(data.encode()) data = clientSocket.recv(1024) if not data: break print("服務器返回的消息是:", data.decode('utf-8')) clientSocket.close()
《Python核心編程》第三版原始代碼P55-56在Python3中並不能運行的問題,算不算一個錯誤呢? 歡迎大家交流 !