在學習socket編程時,遇到代碼返回如下錯誤: TypeError: a bytes-like object is required, not 'str'
發現這里python3.5和Python2.7在套接字返回值解碼上有區別。
首先可以明確,在python3中默認的編碼方式是unicode。unicode 分為 utf-32(占4個字節),utf-16(占兩個字節),utf-8(占1-4個字節),因此 utf-16就是現在最常用的unicode版本。 不過考慮到utf8省空間,在文件里存的還是utf-8。
書中示例
服務端
1 #coding=utf-8 2 #創建TCP服務器 3 from socket import * 4 from time import ctime 5 6 HOST='' 7 PORT=21567 8 BUFSIZ=1024 9 ADDR=(HOST,PORT) 10 11 tcpSerSock=socket(AF_INET,SOCK_STREAM) #創服務器套接字 12 tcpSerSock.bind(ADDR) #套接字與地址綁定 13 tcpSerSock.listen(5) #監聽連接,傳入連接請求的最大數 14 15 while True: 16 print('waiting for connection...') 17 tcpCliSock,addr =tcpSerSock.accept() 18 print('...connected from:',addr) 19 20 while True: 21 data =tcpCliSock.recv(BUFSIZ) 22 #print('date=',data) 23 if not data: 24 break 25 tcpCliSock.send(('[%s] %s' %(ctime(),data))) 26 27 tcpCliSock.close() 28 tcpSerSock.close()
客戶端
1 #coding=utf-8 2 3 from socket import * 4 5 HOST = 'localhost' # or 'localhost' 6 PORT = 21567 7 BUFSIZ = 1024 8 ADDR=(HOST,PORT) 9 10 tcpCliSock = socket(AF_INET,SOCK_STREAM) 11 tcpCliSock.connect(ADDR) 12 13 while True: 14 data = input('> ') 15 print('data=',data); 16 if not data: 17 break 18 tcpCliSock.send(data) 19 data = tcpCliSock.recv(BUFSIZ) 20 if not data: 21 break 22 print(data) 23 24 tcpCliSock.close()
返回的錯誤提示:
TypeError: a bytes-like object is required, not ‘str’
輸入信息時,在客戶端輸入的是字符串(str類型),而代碼中需要的是bytes類型,帶着疑問去查原因,最終在StackOverflow上發現有人也出現同樣的問題,且一個叫Scharron的人給出了解答:
In python 3, bytes strings and unicodestrings are now two different types. Since sockets are not aware of string encodings, they are using raw bytes strings, that have a slightly differentinterface from unicode strings.
So, now, whenever you have a unicode string that you need to use as a byte string, you need to encode() it. And whenyou have a byte string, you need to decode it to use it as a regular(python 2.x) string.
Unicode strings are quotes enclosedstrings. Bytes strings are being enclosed strings.
When you use client_socket.send(data),replace it by client_socket.send(data.encode()). When you get datausing data = client_socket.recv(512), replace it by data =client_socket.recv(512).decode()
因此,客戶端傳輸信息時需要解碼把 str類型 轉換 bytes類型 用於傳輸,在接收到服務端信息后,需要進行編碼,再把 bytes類型 轉換成 str類型
以下為修改后的代碼:
服務端
1 #coding=utf-8 2 #創建TCP服務器 3 from socket import * 4 from time import ctime 5 6 HOST='' 7 PORT=21567 8 BUFSIZ=1024 9 ADDR=(HOST,PORT) 10 11 tcpSerSock=socket(AF_INET,SOCK_STREAM) #創服務器套接字 12 tcpSerSock.bind(ADDR) #套接字與地址綁定 13 tcpSerSock.listen(5) #監聽連接,傳入連接請求的最大數 14 15 while True: 16 print('waiting for connection...') 17 tcpCliSock,addr =tcpSerSock.accept() 18 print('...connected from:',addr) 19 20 while True: 21 data =tcpCliSock.recv(BUFSIZ).decode() 22 print('date=',data) 23 if not data: 24 break 25 tcpCliSock.send(('[%s] %s' %(ctime(),data)).encode()) 26 27 tcpCliSock.close() 28 tcpSerSock.close()
客戶端
#coding=utf-8 #創建TCP服務器 from socket import * from time import ctime HOST='' PORT=21567 BUFSIZ=1024 ADDR=(HOST,PORT) tcpSerSock=socket(AF_INET,SOCK_STREAM) #創服務器套接字 tcpSerSock.bind(ADDR) #套接字與地址綁定 tcpSerSock.listen(5) #監聽連接,傳入連接請求的最大數 while True: print('waiting for connection...') tcpCliSock,addr =tcpSerSock.accept() print('...connected from:',addr) while True: data =tcpCliSock.recv(BUFSIZ).decode() print('date=',data) if not data: break tcpCliSock.send(('[%s] %s' %(ctime(),data)).encode()) tcpCliSock.close() tcpSerSock.close()
歡迎各位指正問題