1. 程式人生 > >Python3.X Socket 一個編碼與解碼的坑

Python3.X Socket 一個編碼與解碼的坑

time() 解碼 oss 數據 tex href real byte 錯誤

最近在看《Python核心編程》第三版 講述網絡編程Socket的知識,在練習中采用Python 3 的代碼中遇到一個與編碼解碼有關的坑,本文將給予詳細的介紹。

軟件環境

Python: 3.6.0
庫: socket

問題初見

仿照書中的代碼(中文版 55-56頁) 加上自己的一點改動在我的環境中不能運行,總是報這個錯誤:
技術分享圖片

這裏是我的客戶端Socket代碼

from socket import *
from time import ctime

HOST = ‘localhost‘
PORT = 10001
ADDRESS = (HOST, PORT)

clientSocket = socket(AF_INET, SOCK_STREAM)
clientSocket.connect(ADDRESS)

while True:
    data = input(‘請輸入消息:‘)
    if not data:
        break

    clientSocket.send(data)
    data = clientSocket.recv(1024)
    if not data:
        break

    print("服務器返回的消息是:", data.decode(‘utf-8‘))

clientSocket.close()

我的環境是: Python 3.6.0, 怎麽破?

研究錯誤 TypeError: a bytes-like object is required, not ‘str‘

錯誤的位置是在代碼clientSocket.send(data)部分,但是翻看python socket .send()源代碼_socket.py 方法說明

def send(self, data, flags=None): # real signature unknown; restored from doc

    send(data[, flags]) -> count

    Send a data string to the socket.  For the optional flags
    argument, see the Unix manual.  Return the number of bytes
    sent; this may be less than len(data) if the network is busy.

    pass

這個方法的參數期望的是一個 "a data string" 啊,而我確實給了一個string。

哪裏出問題了? 繼續查看官方文檔,發現原因了

官方文檔對Socket的說明:
https://docs.python.org/3/library/socket.html
socket.send(bytes[, flags])

可以看到在Python 3中send()方法期望的是一個bytes, 而不是str
看來我我前面看到的是假的源代碼參數的說明。哈哈。

用encode() 方法解決客戶端Socket 發送錯誤

解決錯誤的方法就是在調用send()方法之前對字符串類型數據進行encode,將字符串轉化成bytes

代碼如下:

clientSocket.send(data.encode())

與此同時,在服務端運行的時候也遇到了類似數據無法接收的問題。
如下代碼得到的data,是無法直接打印的。
data = clientSocket.recv(1024)

如果要打印data數據的話,也要調用decode()從而將數據從bytes轉化為str。

encode() 和 decode()

encode()編碼 : str -> bytes
decode()解碼 : bytes -> str

默認的encoding是 utf-8

官方文檔:
str.encode()
bytes.decode()

完整Socket代碼

服務端:

from socket import *
from time import ctime

HOST = ‘localhost‘
PORT = 10001
ADDRESS = (HOST, PORT)

serverSocket = socket(AF_INET, SOCK_STREAM)
serverSocket.bind(ADDRESS)
serverSocket.listen(5)

while True:
    print("等待客戶端連接...")
    clientSocket, address = serverSocket.accept()
    print(address, "已經成功連接至本服務器")

    while True:
        data = clientSocket.recv(1024)
        if not data:
            break

        replyMsg = data.decode() + "[" + ctime() + ‘]‘
        clientSocket.send(replyMsg.encode())

    clientSocket.close()
serverSocket.close()

客戶端:

from socket import *
from time import ctime

HOST = ‘localhost‘
PORT = 10001
ADDRESS = (HOST, PORT)

clientSocket = socket(AF_INET, SOCK_STREAM)
clientSocket.connect(ADDRESS)

while True:
    data = input(‘請輸入消息:‘)
    if not data:
        break

    clientSocket.send(data.encode())
    data = clientSocket.recv(1024)
    if not data:
        break

    print("服務器返回的消息是:", data.decode(‘utf-8‘))

clientSocket.close()

《Python核心編程》第三版原始代碼P55-56在Python3中並不能運行的問題,算不算一個錯誤呢?

Python3.X Socket 一個編碼與解碼的坑