【Socket通訊】關於Socket通訊原理解析及python實現

Socket(套接字)通訊{網絡通訊其實就是Socket間的通訊},首先了解下概念:【來源於百度百科】python

"兩個程序經過一個雙向的通訊鏈接實現數據的交換,這個鏈接的一端稱爲一個socket。"

能夠這麼說,Socket就是一個網絡編程的接口(API),它定義了一種標準,並對TCP/IP進行封裝,實現了網絡傳輸數據的能力。編程

這篇文章默認您已經瞭解IP、端口等基本網絡概念,如未了解,請移步:https://baike.baidu.com/item/IP/224599安全

咱們想象這麼一個場景,若是兩我的,想要互相送一份禮物【用某風快遞】,那麼每一個人都須要知道對方的什麼信息?服務器

  1. 地址【IP】:否則你讓快遞公司送到哪裏?【否則你讓互聯網提供商把數據送到哪臺電腦?】
  2. 姓名【端口】:一個地點不必定住一我的啊,快遞小哥怎麼知道要送給誰?【一臺電腦不必定只有一個程序使用網絡啊,系統怎麼知道把數據傳給哪一個程序?】

再一點,快遞公司有不少種,不必定非得選擇某風快遞,你也能夠用某通快遞、某達快遞、某國郵政之類的,各有各的特色。在socket通訊中也是這樣,分爲TCP、UDP兩種。網絡

TCP(Transmission Control Protocol,傳輸控制協議)是基於鏈接的協議,也就是說,在正式收發數據前,必須和對方創建可靠的鏈接異步

UDP(User Data Protocol,用戶數據報協議)是與TCP相對應的協議。它是面向非鏈接的協議,它不與對方創建鏈接,而是直接就把數據包發送過去socket

關鍵詞我已經標記出來了,配合上面的情景引入,能夠很容易的理解。既然各有各的特點,那麼根據生物學定理:「結構決定功能」,咱們也很容易知道這倆東西確定有不同的地方。函數

TCP,因爲是基於雙方鏈接的狀況下傳輸的,所以它的鏈接以及數據傳輸是很是穩定可靠的,可使一臺計算機發出的字節流無缺無損的發生給另外一臺計算機。對要求可靠性很是高的應用程序會選擇此種通訊方式。網站

UDP,確定是不太穩定的了,它適用於一次只傳送少許數據、對可靠性要求不高的應用環境。其實咱們經常使用的【ping】命令的工做原理就是向對方主機發送ICMP數據包【自行百度】,而後對方主機確認收到數據包,若是數據包是否到達的消息及時反饋回來,那麼網絡就是通的。對了,QQ的聊天功能大部分是用UDP來實現的,由於這樣可使得傳輸速率極快,但同時也會出現發生失敗的狀況,更極端的就是遇到掉包的狀況。spa

另外,關於Socket通訊還需理解的兩對概念:長鏈接與短鏈接異步與同步【這個概念理解起來較難,但你能夠先不理解,不會妨礙你實現小項目,在你實現完幾個小項目後,再反過來看這塊,你會有恍然大悟的感受】

一、長鏈接 
       顧名思義,長鏈接就是鏈接時間更長的鏈接方式:鏈接——>傳輸數據——>等待——>傳輸數據…………——>結束
       Socket不管在是否使用都處於鏈接狀態,雖然佔用資源更小,但安全性較差。

二、短鏈接
        一樣也是顧名思義,短鏈接就是鏈接時間更短的鏈接方式,但會屢次鏈接:鏈接——>傳輸數據——>結束  鏈接——>傳輸數據…………——>結束
       SOCKET鏈接後發送後接收完數據後立刻斷開鏈接。

 

一、異步 
       報文發送和接收是分開的,相互獨立的,互不影響。這種方式又分兩種狀況: 
       (1)異步雙工:接收和發送在同一個程序中,由兩個不一樣的子進程分別負責發送和接收 
       (2)異步單工:接收和發送是用兩個不一樣的程序來完成。 

二、同步 
       報文發送和接收是同步進行,既報文發送後等待接收返回報文。 同步方式通常須要考慮超時問題,即報文發出去後不能無限等待,須要設定超時時間,超過該時間發送方再也不等待讀返回報文,直接通知超時返回。
       在長鏈接中通常是沒有條件可以判斷讀寫何時結束,因此必需要加長度報文頭。讀函數先是讀取報文頭的長度,再根據這個長度去讀相應長度的報文。  

原諒我,同步異步實在沒找到合適的圖,我也實在想不出怎麼來舉栗子能讓讀者更好的理解。我我的經歷是:作了個評測機【評測機和網站服務器間用socket傳輸數據】後才理解的。

下面咱們就得了解這些快遞公司到底如何實現交互的?

先看這個圖,其實這個圖就能夠歸納一切了,可是爲了讓大部分更好的理解,我再解釋下的。

首先,客戶端和服務端會分別新建一個socket,服務端的socket須要經過bind()來綁定上端口,啓動listen()進行實時監聽,並等待客戶端的接入,即accept()。而客戶端則須要經過服務器IP和端口兩個參數來創建connect()鏈接,此時,服務器會獲得有新客戶端鏈接的信息,啓動read()等待客戶端數據的傳人,客戶端若是成功接收到服務端的鏈接成功後,繼續執行write()來向服務端發生數據,同理,服務端也使用這樣的模式回饋客戶端的數據,知道客戶端關閉,服務端會收到客戶端退出鏈接的消息,服務器從新進入等待狀態,等待新客戶端的進入。

下面是用python寫的示例,其餘語言也都遵循上面的標準,C++採用的擴展庫來實現的,在<WINSOCKET2>這個庫中實現。

 1 import socket
 2 #服務端
 3 new_socket = socket.socket()         # 建立 socket 對象
 4 ip = "127.0.0.1"          # 獲取本地主機名
 5 port = 52052                # 設置端口
 6 new_socket.bind((ip, port))        # 綁定端口
 7 new_socket.listen(5)                 # 等待客戶端鏈接並設置最大鏈接數
 8 while True:
 9     new_cil, addr = new_socket.accept()     # 創建客戶端鏈接。
10     print('新進來的客戶端的地址:', addr)
11     print(new_cil.recv().decode())
12     new_cil.send('答案爲6')
13     new_cil.close()                # 關閉鏈接
import socket
#客戶端
ip = "127.0.0.1"
port = 52052
new_socket = socket.socket()  #建立socket對象
new_socket.connect((ip,port))  #鏈接
new_socket.send("請求給我計算下1+5=多少?".encode(encoding='utf-8')) #發生數據
print("客戶端發給服務端:請求給我計算下1+5=多少?") 
back_str = new_socket.recv().decode() #結束數據
print("服務端發給客戶端:"+back_str)
new_socket.close() #關閉客戶端
print("客戶端結束運行")

 

人生苦短,我用python!隔壁C語言實現這個至少200行代碼!

相關文章
相關標籤/搜索