1. 程式人生 > >Python網路程式設計socket模組例項解析

Python網路程式設計socket模組例項解析

socket通常也稱作”套接字”,用於描述IP地址和埠,是一個通訊鏈的控制代碼,應用程式通常通過”套接字”向網路發出請求或者應答網路請求。

socket起源於Unix,而Unix/Linux基本哲學之一就是“一切皆檔案”,對於檔案用【開啟】【讀寫】【關閉】模式來操作。socket就是該模式的一個實現,socket即是一種特殊的檔案,一些socket函式就是對其進行的操作(讀/寫IO、開啟、關閉)。

(1)利用socket進行簡單的連結

Python裡面的socket支援UDP、TCP、以及程序間的通訊,socket可以把我們想要傳送的東西封裝起來,傳送過去,然後反解成原來的樣子,事實上網路通訊可以理解成都是建立在socket之上,下面的程式碼是演示利用socket進行簡單的連結

#要成一次通訊,至少要有兩個人,也就是一個服務端,一個客戶端
 
#服務端
'''必須先開啟著,等待客戶端來進行連結請求,所以自己要先有個地址,也就是IP,也要現有自己的埠,沒有埠進不去'''
 
import socket
sk= socket.socket()#建立物件
 
sk.bind(('127.0.0.1',9999,))#繫結IP和埠,以一個元組的方式傳進去
sk.listen(5)#在前面連結已經建立的情況下,後面最多讓五個人等待
while True:#讓伺服器端處於可以永遠處於接受客戶端請求的狀態
 
    conn,address=sk.accept()
    print(conn,address)
'''
監聽埠,等待以及接受客戶端的請求,有可能會阻塞,主要功能是建立連結,以及接受客戶端資訊
conn相當於雙方建立的這個連結,之後互相的通訊要依靠這個連結;
address指的的對方的IP和埠
'''

下面是客戶端程式碼

#客戶端
import socket
obj =socket.socket()
'''相對於客戶端,制定要連結誰就好了
'''
 
obj.connect(('127.0.0.1',9999,))#連結服務端
obj.close()#連結之後關閉

我們先讓伺服器端啟動,然後再啟動客戶端,結果如圖所示

Python網路程式設計socket模組例項解析

<socket.socket fd=4, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 36126)> ('127.0.0.1', 36126)
<socket.socket fd=5, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 36128)> ('127.0.0.1', 36128)
<socket.socket fd=4, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 36130)> ('127.0.0.1', 36130)

成功打印出了每次的連結,以及客戶端的IP以及埠號

(2)基於socket實現簡單的傳送訊息

然後用是客戶端程式碼

#客戶端
import socket
obj =socket.socket()
'''相對於客戶端,制定要連結誰就好了
'''
 
obj.connect(('127.0.0.1',9999,))#連結服務端
'''
客戶端去連結服務端,如果伺服器端沒有返回訊息給客戶端,則客戶端會一直
在recv狀態,一直等待伺服器的訊息
'''
result1= obj.recv(2014)#表示最多接收1024個位元組,超過了下次接收、
result2= str(result1,encoding='utf-8')
print(result2)
obj.close()#連結之後關閉

當啟動一次客戶端建立一次連結,就會收到訊息,結果如圖

Python網路程式設計socket模組例項解析

(3)基於socket實現聊天機器人

下面是客戶端程式碼

#客戶端
import socket
obj =socket.socket()
'''相對於客戶端,制定要連結誰就好了
'''
 
obj.connect(('127.0.0.1',9999,))#連結服務端
'''
客戶端去連結服務端,如果伺服器端沒有返回訊息給客戶端,則客戶端會一直
在recv狀態,一直等待伺服器的訊息
'''
 
result1= obj.recv(2014)#表示最多接收1024個位元組,超過了下次接收、
result2= str(result1,encoding='utf-8')
print(result2)
while True:
    data = input('請輸入你要傳送的內容:')
    if data == 'q':
        obj.sendall(bytes(data, encoding='utf-8'))
        print('連結斷開')
        break
    else:
        obj.sendall(bytes(data,encoding='utf-8'))
        rec_byte = obj.recv(1024)#發了之後,接收資訊
        rec_str = str(rec_byte,encoding='utf-8')
        print(rec_str)
 
obj.close()#連結之後關閉

結果如圖所示

Python網路程式設計socket模組例項解析

 (4)利用socket傳送圖片檔案

下面是客戶端

結果如圖

Python網路程式設計socket模組例項解析

(5)socket粘包問題

傳送檔案需要依賴雙方的緩衝區,就是我們先把檔案寫到緩衝區,然後再發送過去,但是我們一般不知道什麼時候發過去,這容易造成粘包問題。例如上面的例子,客戶端先發送檔案大小,然後讀檔案寫進緩衝區,假如檔案讀取特別快,第一次傳送過去的可能既有檔案大小又有檔案內容,造成錯誤,這叫粘包,簡而言之就是收到的資訊比原本應收的多。

那麼怎麼解決粘包問題呢,通過傳送以及接收確認包,還是以上面的例子說明,客戶在傳送檔案大小之後不要馬上傳送檔案,先recv接收一下,等待伺服器傳送已收到檔案大小的確認包之後,再讀取檔案、傳送檔案,這樣檔案的傳送和之前資料的傳送就
完全獨立開來了。

下面是客戶端

Python網路程式設計socket模組例項解析