標籤:表示 inet6 ext 一個 迴文 分享 顯示 情況 指定
Python 中的網路編程
一、socket()模組
二、建立TCP伺服器
三、建立TCP用戶端
一、socket模組
通訊端:
通訊端最初是為同一主機上的應用程式所建立,使得主機上啟動並執行一個程式(又名一個 進程)與另一個啟動並執行程式進行通訊。這就是所謂的處理序間通訊(Inter Process Communication, IPC)。有兩種類型的通訊端:基於檔案的和面向網路的。總的來說,Python 只支援 AF_UNIX、AF_NETLINK、AF_TIPC 和 AF_INET 家族。
socket()模組函數 要建立通訊端,必須使用 socket.socket()函數,它一般的文法 :
1 socket(socket_family, socket_type, protocol=0)
其中,socket_family是AF_UNIX或AF_INET(如前所述),socket_type是SOCK_STREAM 或 SOCK_DGRAM(也如前所述)。protocol通常省略,預設為 0。
所以,為了建立 TCP/IP 通訊端,可以用下面的方式調用 socket.socket()。
tcpSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
同樣,為了建立 UDP/IP 通訊端,需要執行以下語句。
udpSock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
因為有很多 socket 模組屬性,所以此時使用“from module import *”這種匯入方式可以 接受,不過這隻是其中的一個例外。如果使用“from socket import *”,那麼我們就把 socket 屬性引入到了命名空間中。雖然這看起來有些麻煩,但是通過這種方式將能夠大大縮短代碼, 正如:
tcpSock = socket(AF_INET, SOCK_STREAM)
表格式查詢
名 字 |
描 述 |
s.send() |
發送 TCP 訊息 |
s.sendall() |
完整地發送 TCP 訊息 |
s.recvfrom() |
接收 UDP 訊息 |
s.recvfrom_into() |
接收 UDP 訊息到指定的緩衝區 |
s.sendto() |
發送 UDP 訊息 |
s.getpeername() |
串連到通訊端(TCP)的遠程地址 |
s.getsockname() |
當前通訊端的地址 |
s.getsockopt() |
返回給定通訊端選項的值 |
s.setsockopt() |
設定給定通訊端選項的值 |
s.shutdown() |
關閉串連 |
s.close() |
關閉通訊端 |
s.detach() |
在未關閉檔案描述符的情況下關閉通訊端,返迴文件描述符 |
s.ioctl() |
控制通訊端的模式(僅支援 Windows) 面向阻塞的通訊端方法 |
s.setblocking() |
設定通訊端的阻塞或非阻塞模式 |
s.settimeout() |
設定阻塞通訊端操作的逾時時間 |
s.gettimeout() |
擷取阻塞通訊端操作的逾時時間 面向檔案的通訊端方法 |
s.makefile() |
建立與通訊端關聯的檔案對象 資料屬性 |
s.family |
通訊端家族 |
s.proto |
通訊端協議 |
二、建立TCP伺服器
建立通用 TCP 伺服器的一般虛擬碼,然後對這些代碼的含義進行一般 性的描述。
ss = socket() # 建立伺服器通訊端 ss.bind() # 通訊端與地址綁定 ss.listen() # 監聽串連inf_loop: # 伺服器無限迴圈 cs = ss.accept() # 接受用戶端串連 comm_loop: # 通訊迴圈 cs.recv()/cs.send() # 對話(接收/發送) cs.close() # 關閉用戶端通訊端 ss.close() # 關閉伺服器通訊端#(可選)
所有通訊端都是通過使用 socket.socket()函數來建立的。因為伺服器需要佔用一個連接埠並 等待用戶端的請求,所以它們必須綁定到一個本地地址。因為 TCP 是一種連線導向的通訊系 統,所以在 TCP 伺服器開始操作之前,必須安裝一些基礎設施。特別地,TCP 伺服器必須監 聽(傳入)的串連。一旦這個安裝過程完成後,伺服器就可以開始它的無限迴圈。
接下來這個指令碼建立一個TCP伺服器,它接受來自用戶端的訊息,然後將訊息加上時間戳記首碼並發送回用戶端
第 6~13 行 HOST 變數是空白的,這是對 bind()方法的標識,表示它可以使用任何可用的地址。我 們也選擇了一個隨機的連接埠號碼,並且該連接埠號碼似乎沒有被使用或被系統保留。另外,對於該 應用程式,將緩衝區大小設定為 1KB。可以根據網路效能和程式需要改變這個容量。listen() 方法的參數是在串連被轉接或拒絕之前,傳入串連請求的最大數。 在第 11 行,分配了 TCP 伺服器通訊端(tcpSerSock),緊隨其後的是將通訊端綁定到服 務器地址以及開啟 TCP 監聽器的調用。
第 15~28 行 一旦進入伺服器的無限迴圈之中,我們就(被動地)等待用戶端的串連。當一個串連請求出 現時,我們進入對話迴圈中,在該迴圈中我們等待用戶端發送的訊息。如果訊息是空白的,這意 味著用戶端已經退出,所以此時我們將跳出對話迴圈,關閉當前用戶端串連,然後等待另一個客 戶端串連。如果確實得到了用戶端發送的訊息,就將其格式化並返回相同的資料,但是會在這些 資料中加上目前時間戳的首碼。
三、建立TCP用戶端
建立用戶端比伺服器要簡單得多。
如:
cs = socket() # 建立用戶端通訊端 cs.connect() # 嘗試串連伺服器 comm_loop: # 通訊迴圈 cs.send()/cs.recv() # 對話(發送/接收) cs.close() # 關閉用戶端通訊端
正如前面提到的,所有通訊端都是利用 socket.socket()建立的。然而,一旦用戶端擁有了 一個通訊端,它就可以利用通訊端的 connect()方法直接建立一個到伺服器的串連。當串連建 立之後,它就可以參與到與伺服器的一個對話中。最後,一旦用戶端完成了它的事務,它就 可以關閉通訊端,終止此次串連。
接下來這個指令碼建立一個TCP用戶端,它提示使用者輸入發送到伺服器端的訊息,並接收從伺服器端返回的添加了時間戳記前 綴的相同訊息,然後將結果展示給使用者。
第 1~3 行 在 UNIX 啟動行後,從 socket 模組匯入所有屬性。 第 5~11 行 HOST 和 PORT 變數指伺服器的主機名稱與連接埠號碼。因為在同一台電腦上運行測試(在 本例中),所以 HOST 包含本地主機名稱(如果你的伺服器運行在另一台主機上,那麼需要進 行相應修改)。連接埠號碼 PORT 應該與你為伺服器設定的完全相同(否則,將無法進行通訊)。 此外,也將緩衝區大小設定為 1KB。 在第 10 行分配了 TCP 用戶端通訊端(tcpCliSock),接著主動調用並串連到伺服器。 第 13~23 行 用戶端也有一個無限迴圈,但這並不意味著它會像伺服器的迴圈一樣永遠運行下去。客戶 端迴圈在以下兩種條件下將會跳出:使用者沒有輸入(第 14~16 行),或者伺服器終止且對 recv() 方法的調用失敗(第 18~20 行)。否則,在正常情況下,使用者輸入一些字串資料,把這些數 據發送到伺服器進行處理。然後,用戶端接收到加了時間戳記的字串,並顯示在螢幕上。在這個程式碼片段中,需要將本地主機修改成它的 IPv6 地址“::1”,同時請求通訊端的 AF_INET6 家族。如果結合 tsTclnt3.py 和 tsTclntV6.py 中的變化,那麼將得到一個 Python 3 版本的 IPv6 TCP 用戶端。
Python 中的網路編程-socket模組、建立TCP伺服器、建立TCP用戶端