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

《python核心编程》第三版,发现示例2-1代码返回错误…..纠结好久 
发现这里python3.5和Python2.7在套接字返回值解码上有区别。 
先介绍一下 python bytes和str两种类型转换的函数encode(),decode()python

  • str经过encode()方法能够编码为指定的bytes
  • 反过来,若是咱们从网络或磁盘上读取了字节流,那么读到的数据就是bytes。要把bytes变为str,就须要用decode()方法:

python核心编程书中的2-1例子

TCP服务器:编程

#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) #print('date=',data) if not data: break tcpCliSock.send(('[%s] %s' %(ctime(),data))) tcpCliSock.close() tcpSerSock.close()

 

TCP客户端服务器

#coding=utf-8 from socket import * HOST = 'localhost' # or 'localhost' PORT = 21567 BUFSIZ = 1024 ADDR=(HOST,PORT) tcpCliSock = socket(AF_INET,SOCK_STREAM) tcpCliSock.connect(ADDR) while True: data = input('> ') print('data=',data); if not data: break tcpCliSock.send(data) data = tcpCliSock.recv(BUFSIZ) if not data: break print(data) tcpCliSock.close() 

 

 

 

返回的错误提示: 
TypeError: a bytes-like object is required, not ‘str’ 
指的是18行tcpCliSock.send(data)传入的参数是应该是bytes类型,而不是str类型。网络

因而我去百度,发如今StackOverflow上发现有人也出现一样的问题,并一个叫Scharron的人提出了解答:app

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.socket

So, now, whenever you have a unicode stringthat you need to use as a byte string, you need toencode() it. And whenyou have a byte string, you need to decode it to use it as a regular(python 2.x) string.tcp

Unicode strings are quotes enclosedstrings. Bytes strings are b”” 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()ui

因而我去查python3.5的帮助手册。this

socket.send(bytes[, flags])

Send data to the socket. The socket must be connected to a remote socket. The optional flags argument has the same meaning as for recv() above. Returns the number of bytes sent. Applications are responsible for checking that all data has been sent; if only some of the data was transmitted, the application needs to attempt delivery of the remaining data. For further information on this topic, consult the Socket Programming HOWTO.

Changed in version 3.5: If the system call is interrupted and the signal handler does not raise an exception, the method now retries the system call instead of raising an InterruptedError exception (see PEP 475 for the rationale).

 

socket.recv(bufsize[, flags])

Receive data from the socket. The return value is a bytes object representing the data received. The maximum amount of data to be received at once is specified by bufsize. See the Unix manual page recv(2) for the meaning of the optional argument flags; it defaults to zero.

Note

For best match with hardware and network realities, the value of bufsize should be a relatively small power of 2, for example, 4096.

Changed in version 3.5: If the system call is interrupted and the signal handler does not raise an exception, the method now retries the system call instead of raising an InterruptedError exception (see PEP 475 for the rationale).

 

修正后:

tcp服务器

#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()

 

tcp客户端:

#coding=utf-8 from socket import * HOST = 'localhost' # or 'localhost' PORT = 21567 BUFSIZ = 1024 ADDR=(HOST,PORT) tcpCliSock = socket(AF_INET,SOCK_STREAM) tcpCliSock.connect(ADDR) while True: data = input('> ') #print('data=',data); if not data: break tcpCliSock.send(data.encode()) data = tcpCliSock.recv(BUFSIZ).decode() if not data: break print(data) tcpCliSock.close()

 

socket.sendto(bytes, address) 
socket.sendto(bytes, flags, address)

Send data to the socket. The socket should not be connected to a remote socket, since the destination socket is specified by address. The optional flags argument has the same meaning as for recv() above. Return the number of bytes sent. (The format of address depends on the address family — see above.)

Changed in version 3.5: If the system call is interrupted and the signal handler does not raise an exception, the method now retries the system call instead of raising an InterruptedError exception (see PEP 475 for the rationale).

 

socket.recvfrom(bufsize[, flags])

Receive data from the socket. The return value is a pair (bytes, address) where bytes is a bytes object representing the data received and address is the address of the socket sending the data. See the Unix manual page recv(2) for the meaning of the optional argument flags; it defaults to zero. (The format of address depends on the address family — see above.)

 

同理修正udp服务器:

from socket import * from time import ctime HOST='' PORT=21546 BUFSIZ=1024 ADDR=(HOST,PORT) udpSerSock = socket(AF_INET,SOCK_DGRAM) udpSerSock.bind(ADDR) while True: print('waiting for message...') data,addr=udpSerSock.recvfrom(BUFSIZ) data=data.decode() udpSerSock.sendto(('[%s] %s'%(ctime(),data)).encode(),addr) print('...received from and returned to:',addr) udpSerSock.close()
相关文章
相关标签/搜索