In the third edition of Python core programming, we found that the return error of example 2-1 code… Tangled for a long time
we found that there is a difference in socket return value decoding between Python 3.5 and python 2.7
let’s first introduce the function encode(), decode() of Python bytes and STR type conversion
STR can be encoded to the specified bytes by encode() method
Conversely, if we read a byte stream from the network or disk, the data we read is bytes. To change bytes into STR, you need to use the decode () method:
2-1 examples in Python core programming book
TCP server:
#coding=utf-8
#Creating a TCP server
from socket import *
from time import ctime HOST='' PORT=21567 BUFSIZ=1024 ADDR=(HOST,PORT) tcpSerSock=socket(AF_INET,SOCK_STREAM) #create server sockets tcpSerSock. bind(ADDR) #Bind the socket to the address tcpSerSock.listen(5) #Listen for connections, pass in the maximum number of connection requests 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 client
#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()
Returned error message.
TypeError: a bytes-like object is required, not ‘str’
This refers to line 18 tcpCliSock.send(data)
where the argument passed in is supposed to be of type bytes, not str.
How to Solve:
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 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.
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()
So I went to check the help manual for python 3.5.
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).
After correction:
TCP server
#coding=utf-8
#Creating a TCP server
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 client:
#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.)
Similarly, modify the UDP server
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()
Similar Posts:
- python 3.6 socket tcp Connect TypeError: a bytes-like object is required, not ‘str’
- Programming udp sockets in python
- Python Error: TypeError: string argument without an encoding
- Code a packet sniffer in python with pcapy exte…
- How to Solve Python socket:[Errno 32] Broken pipe
- python TypeError: an integer is required
- [Solved] Typeerror: incorrect padding occurred in python3 Base64 decoding
- Windows: Socket Server Failed to bind, error 10048 [How to Solve]
- Error reporting and resolution of Python 3 using binascii method
- Using Python HDFS module to operate Hadoop HDFS