1. 程式人生 > >Python 中的網絡編程-socket模塊、創建TCP服務器、創建TCP客戶端

Python 中的網絡編程-socket模塊、創建TCP服務器、創建TCP客戶端

src strong lin nec 並發 變量 通過 參數 round

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客戶端