在学习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()
欢迎各位指正问题