1. 程式人生 > 其它 >什麼是Python中的套接字程式設計?

什麼是Python中的套接字程式設計?

摘要:本文涵蓋了有關使用Python進行套接字程式設計的所有領域。套接字可以幫助您建立這些連線,而Python無疑可以簡化連線。

本文分享自華為雲社群《從零開始學python |什麼是Python中的套接字程式設計以及如何掌握它?》,原文作者:Yuchuan。

不可否認,網際網路已成為“存在之魂”,其活動以“連線”或“網路”為特徵。使用套接字的最關鍵的基礎之一,使這些網路成為可能。本文涵蓋了有關使用Python進行套接字程式設計的所有領域。套接字可以幫助您建立這些連線,而Python無疑可以簡化連線。

讓我們快速看一下本文涵蓋的所有主題:

Why use Sockets?
What are Sockets in Python?
How to achieve Socket Programming in Python
What is a server?
What is a client?
Echo Client-Server
Multiple Communications
Transferring Python Objects

  • Python pickle module
  • How to transfer python objects using the pickle module

Why use Sockets?

套接字是網路的基礎。它們使在兩個不同程式或裝置之間的資訊傳輸成為可能。例如,當您開啟瀏覽器時,您作為客戶端正在與伺服器建立連線以進行資訊傳輸。

在深入探討這種通訊之前,讓我們首先弄清楚這些插座的確切含義。

What are Sockets?

一般而言,套接字是為傳送和接收資料而構建的內部端點。單個網路將具有兩個套接字,每個通訊裝置或程式一個。這些套接字是IP地址和埠的組合。根據所使用的埠號,單個裝置可以具有n個插槽。不同的埠可用於不同型別的協議。請看以下影象,以瞭解有關一些常見埠號和相關協議的更多資訊:

現在您已經瞭解了套接字的概念,現在讓我們看一下Python的Socket模組:

如何在Python中實現Socket程式設計:

要使用Python實現Socket程式設計,您將需要匯入socket模組或框架。該模組由建立套接字並幫助它們彼此關聯所需的內建方法組成。

一些重要的方法如下:

既然您已經瞭解了套接字模組的重要性,那麼讓我們繼續看一下它如何為Python中的套接字程式設計建立伺服器和客戶端。

什麼是伺服器?

伺服器可以是程式,計算機或專用於管理網路資源的裝置。伺服器可以在同一臺裝置或計算機上,也可以在本地連線到其他裝置和計算機,甚至可以遠端連線。有各種型別的伺服器,例如資料庫伺服器,網路伺服器,列印伺服器等。

伺服器通常使用諸如socket.socket(),socket.bind(),socket.listen()等方法來建立連線並繫結到客戶端。現在,讓我們編寫一個程式來建立伺服器。考慮以下示例:

例子:

import socket
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((socket.gethostname(),1234))          
#port number can be anything between 0-65535(we usually specify non-previleged ports which are > 1023)
s.listen(5)
 
while True:
    clt,adr=s.accept()
    print(f"Connection to {adr}established")  
   #f string is literal string prefixed with f which 
   #contains python expressions inside braces
    clt.send(bytes("Socket Programming in Python","utf-8 ")) #to send info to clientsocket

如您所見,建立套接字的第一個必要條件是匯入套接字模組。之後,使用socket.socket()方法建立伺服器端套接字。

NOTE:

AF_INET是指Internet上的地址,它需要一對(主機,埠),其中主機可以是某個特定網站的URL或它的地址,並且埠號是整數。SOCK_STREAM用於建立TCP協議。

bind()方法接受兩個引數作為元組(主機,埠)。但是,最好使用4位數字的埠號,因為通常佔用較小的埠號。listen()方法允許伺服器接受連線。在這裡,5是同時出現的多個連線的佇列。此處可以指定的最小值為0(如果您提供較小的值,則將其更改為0)。如果未指定任何引數,則採用預設的合適引數。

在while迴圈允許接受連線永遠。“ clt”和“ adr”是客戶端物件和地址。print語句僅打印出客戶端套接字的地址和埠號。最後,clt.send用於傳送位元組資料。

現在我們的伺服器已經準備好了,讓我們繼續前進到客戶端。

什麼是客戶端?

客戶端是從伺服器接收資訊或服務的計算機或軟體。在客戶端伺服器模組中,客戶端從伺服器請求服務。最好的例子是Web瀏覽器,例如Google Chrome,Firefox等。這些Web瀏覽器向Web伺服器請求使用者指示的所需網頁和服務。其他示例包括線上遊戲,線上聊天等。

現在讓我們看一下如何用Python程式語言編寫客戶端程式:

例子:

import socket
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((socket.gethostname(), 2346))
msg=s.recv(1024)
print(msg.decode("utf-8"))

第一步是匯入套接字模組,然後建立套接字,就像建立伺服器時一樣。然後,要在客戶端-伺服器之間建立連線,您需要通過指定(主機,埠)使用connect()方法。

注意:當客戶端和伺服器位於同一臺計算機上時,將使用gethostname。(LAN –本地IP / WAN –公用IP)

在這裡,客戶端希望從伺服器接收一些資訊,為此,您需要使用recv()方法,並且該資訊儲存在另一個變數msg中。請記住,傳遞的資訊將以位元組為單位,並且在上述程式的客戶端中,一次傳輸最多可接收1024個位元組(緩衝區大小)。可以指定任意數量,具體取決於傳輸的資訊量。

最後,正在傳輸的訊息應進行解碼和列印。

既然您已經知道如何建立客戶端-伺服器程式,那麼讓我們繼續看看如何執行它們。

Echo Client-Server:

要執行這些程式,請開啟命令提示符,進入建立了客戶端和伺服器程式的資料夾,然後鍵入:

py server.py(在這裡,server.py是伺服器的檔名,您也可以使用py -3.7 server.py)

完成此操作後,伺服器將開始執行。要執行客戶端,請開啟另一個cmd視窗,然後鍵入:

py client.py(此處,client.py是客戶端的檔名)

輸出(伺服器):

(客戶)

讓我們通過將緩衝區大小減小到7來嘗試相同的程式,然後看看我們得到什麼輸出:
輸出:

如您所見,連線在傳輸7個位元組後終止。但這是一個問題,因為您尚未收到完整的資訊,並且連線已關閉。讓我們繼續解決這個問題。

Multiple Communications:

為了使連線一直持續到客戶端收到完整的資訊,可以使用while迴圈:

例子:

import socket
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((socket.gethostname(), 2346))
while True:
msg=s.recv(7)
print(msg.decode("utf-8"))

完成此操作後,每次傳輸將以7個位元組的形式接收完整的訊息。

但是這一次,如您所見,連線不會終止,您也不知道何時會發生連線。除此之外,如果您實際上不知道客戶端將從伺服器接收到的訊息或資訊有多大,該怎麼辦。在這種情況下,您實際上可以在客戶端使用以下程式碼:

例子:

complete_info=''
while True:
    msg = s.recv(7)  
    if len(msg)<=0:
        break
    complete_info += msg.decode("utf-8")
print(complete_info)

在伺服器端,使用close()方法,如下所示:

clt.close()

輸出如下圖所示:

輸出:

上面的程式碼塊所做的全部工作是,檢查資訊的大小,並一次將其列印在兩個位元組的緩衝區中,再在完成連線後將其關閉。

傳輸Python物件:

直到這裡,您才有了傳輸字串的訣竅。但是,Python中的套接字程式設計也允許您傳輸Python物件。這些物件可以是集合,元組,字典等任何物件。要實現此目的,您將需要匯入Python的pickle模組。

Python pickle模組:

當您實際上在python中序列化或反序列化物件時,Python pickle模組就會出現。讓我們看一個小例子,

例子:

import pickle
 
mylist=[1,2,'abc']
mymsg = pickle.dumps(mylist) 
print(mymsg)

輸出:b'x80x03] qx00(Kx01Kx02Xx03x00x00x00abcqx01e。

如您所見,在上面的程式中,使用pickle模組的dumps()函式對'mylist'進行了序列化。還要注意,輸出以“ b”開頭,這意味著它已轉換為位元組。在套接字程式設計中,可以實現此模組以在客戶端和伺服器之間傳輸python物件。

如何使用pickle模組傳遞python物件結構?

當您將泡菜與套接字一起使用時,您絕對可以通過網路傳輸任何內容。讓我們寫下伺服器端和客戶端對應項,以將列表從伺服器傳輸到客戶端:

伺服器端:

import socket
import pickle
 
a=10
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((socket.gethostname(), 2133))        #binding tuple
s.listen(5)
while True:
    clt , adr = s.accept()
    print(f"Connection to {adr}established")
 
    m={1:"Client", 2:"Server"}
    mymsg = pickle.dumps(m)  #the msg we want to print later
    mymsg = {len(mymsg):{a}}"utf-8") + mymsg
    clt.send(mymsg)

在這裡,m是一個字典,它基本上是一個python物件,需要從伺服器傳送到客戶端。這是通過首先使用dumps()序列化物件,然後將其轉換為位元組來完成的。現在讓我們寫下客戶端對應的內容:

客戶端:

import socket
import pickle
a=10
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((socket.gethostname(), 2133))
 
while True:
    complete_info = b''
    rec_msg = True
    while True:
        mymsg = s.recv(10)
       if rec_msg:
            print(f"The length of message = {mymsg[:a]}")
            x = int (mymsg[:a ] )
            rec_msg = False
            complete_info += mymsg
            if len(complete_info)-a == x:
            print("Recieved the complete info")
            print(complete_info[a:])
            m = pickle.loads(complete_info[a:])
            print(m)
            rec_msg = True
complete_info = b''
print(complete_info)

第一個while迴圈將幫助我們跟蹤完整訊息(complete_info)以及正在使用緩衝區接收的訊息(rec_msg)。通過設定rec_設定訊息,然後,在接收訊息時,我所做的就是列印每個訊息,並在大小為10的緩衝區中接收該訊息。此大小可以是任何值,具體取決於您的個人選擇。

然後,如果收到的訊息等於完整的訊息,那麼我只是將訊息列印為已接收的完整資訊,然後使用loads()將訊息反序列化。上面程式的輸出如下:

這使我們結束了有關使用Socket進行程式設計的本文的結尾。希望您能清楚地理解所有概念。

點選關注,第一時間瞭解華為雲新鮮技術~