Socket 是應用層和傳輸層之間的壹層抽象協議,可以用來進行進程間通信,壹般有 UDP 和 TCP 兩種通信方式,前者速度稍快,穩定性不好,無法丟包重傳。後者速度稍慢壹點,但穩定性很好,可以丟包重傳。
本文首先介紹使用 Socket 進行 UDP 通信。
使用 Socket 進行 UDP 通信的流程如下:
下面依次進行講解。
要進行 Socket 通信,我們需要使用 socket 模塊,首先需要創建壹個 Socket 對象。下面是兩種創建方式:
如果我們需要向別的主機發送數據,我們需要改主機的 IP 地址和相應的端口號。在使用 Socket 進行通信時,需要將兩個信息寫在壹元組中,元組的第壹項為目標主機 IP 地址,第二項為接受數據的端口號:
其中,IP 地址使用字符串類型,端口號使用數字類型。
如果不綁定端口,每次使用 Socket 時都會由操作系統動態分配壹個端口,我們也可以綁定為某個固定的端口。這樣做的好處是:如果我們想要接受其他主機的信息,其他主機可以直接向這個端口發送數據,如果使用動態端口的話,發送方並不知道目標端口是什麽,因此無法向接收方發送數據。
綁定端口需要使用 Socket 對象的 bind 方法:
bind 方法接受壹個元組作為參數,元組的第壹項為綁定的 IP 地址,第二項為綁定的端口號。我們可以把第壹項指定為本機上的任意壹個 IP 地址,也可以設置為壹個空字符串 "" ,表示本機上任意合法的 IP 地址。
使用 UDP 套接字協議時,發送數據使用 Socket 對象的 sendto 方法,接受數據使用 Socket 對象的 recvfrom 方法。這兩個方法的使用方式如下:
sendto 方法接受兩個參數:發送的數據和目標主機的 IP 和端口元組,在 Python3 中,發送的數據應該轉為 byte 類型發送,Python2 中可以直接發送字符串。
recvfrom 接受壹個參數:本次接受的最大數據尺寸。該方法是阻塞的,只有在接收到數據後才能進行後續的操作。
就像使用文件那樣,在使用完套接字後,需要關閉它,調用 close 方法即可。
上面我們介紹了 Socket 的使用方式,下面我們來做壹個單工通信的例子(壹方負責發送信息,壹方負責接收信息)。
我們這裏來創建兩個文件:用以發送信息的 send.py 和用以接收信息的 recv.py。該實例在虛擬機中模擬(註意將虛擬機設置為橋接模式)。
創建 send.py:
創建 recv.py:
運行結果如下:
上面實現了壹個單工通信的例子:壹方負責發,壹方負責接收。下面我們繼續實現壹個雙工通信的例子,使雙方都能夠收發消息。
由於接收和發送消息時是使用 while 循環不斷輪詢的,因此要實現同時發送和接受,我們需要進行多任務處理。
新建壹個 msg.py:
這裏我們使用 3000 端口發送數據,3001 端口接收數據,運行程序時只需填寫目標主機的 IP 地址,就可以進行通信。
運行效果:
我們還可以進行局域網內的廣播,只需對 Socket 加上壹條設置:
同時,發送廣播需要壹個廣播地址,以及目標主機接受廣播的端口:
上面的設置只能給 0 網段的主機發送廣播,要想給局域網中所有的主機發送廣播,可以這樣設置:
下面我們新建壹個 send.py 用來發送廣播:
新建壹個 recv.py 用來接收廣播:
運行效果如圖:
完。