《python核心編程》第三版,發現示例2-1代碼返回錯誤…..糾結好久
發現這裏python3.5和Python2.7在套接字返回值解碼上有區別。
先介紹一下 python bytes和str兩種類型轉換的函數encode(),decode()python
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.)
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()