1. 程式人生 > >Python網絡編程(一)

Python網絡編程(一)

ted port require 需要 sci sock peer required bin

最近在啃《python核心編程(第三版)》,感覺這本書並不是特別的友好,雖然有基於python3提出的改進代碼;但是整書的基準感覺還是在python2.7。所以python3的代碼中還是有較多的錯誤;就比如第二章網絡編程中:
原代碼:

創建TCP服務器

#coding=utf-8
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() 

如果我們按照這個代碼跑,python3會報出:TypeError: a bytes-like object is required, not ‘str‘ 的錯誤。當時我就很納悶,python2.7中明明是適用的,怎麽到python3中就為‘str‘了?報錯的原因是tcpCliSock.send(data)傳入的參數應該是bytes類型,而不是str類型。
關於這個的解釋為python3與python2.7中關於編碼解碼的規則不同,請看下面。

關於編碼

(引用自廖雪峰老師的教程)
由於Python的字符串類型是str,在內存中以Unicode表示,一個字符對應若幹個字節。如果要在網絡上傳輸,或者保存到磁盤上,就需要把str變為以字節為單位的bytes。

Python對bytes類型的數據用帶b前綴的單引號或雙引號表示:b‘ABC純英文的str可以用ASCII編碼為bytes,內容是一樣的,含有中文的str可以用UTF-8編碼為bytes。含有中文的str無法用ASCII編碼,因為中文編碼的範圍超過了ASCII編碼的範圍,Python會報錯。
在bytes中,無法顯示為ASCII字符的字節,用\x##顯示。
反過來,如果我們從網絡或磁盤上讀取了字節流,那麽讀到的數據就是bytes。要把bytes變為str,就需要用decode()方法。

修改後的代碼

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('等待連接中')
    tcpCliSock, addr = tcpSerSock.accept()
    print('...connected from:', addr)

    while True:
        data = tcpCliSock.recv(BUFSIZ)
        if not data:
            break
        tcpCliSock.send(('[%s] %s' % (ctime(), data)).encode())

    tcpCliSock.close()
tcpSerSock.close()
from socket import *

HOST = '127.0.0.1'
PORT = 21567
BUFSIZ = 1024
ADDR =(HOST, PORT)

tcpCliSock = socket(AF_INET, SOCK_STREAM)
tcpCliSock.connect(ADDR)

while True:
    data = input()
    if not data:
        break
    tcpCliSock.send(data.encode())
    data = tcpCliSock.recv(BUFSIZ).decode()
    if not data:
        break
    print(data)

tcpCliSock.close()

Python網絡編程(一)