Python Socket TypeError: a bytes-like object is required, not 'str' 錯誤提示


在學習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()

歡迎各位指正問題


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM