網路編程就是撰寫程式使兩臺聯網的計算機相互交換資料,
那么,這兩臺計算機之間用什么傳輸資料呢?首先你肯定先需要物理連接嘛,
在此基礎上,只需要考慮如何撰寫資料傳輸程式,看似很麻煩,但實際上這點不用愁,因為作業系統已經提供了 socket,即使對網路資料傳輸的原理不太熟悉,我們也能通過 socket 來編程,
一、什么是socket
socket 的原意是“插座”,在計算機通信領域,socket 被翻譯為“套接字”,它是計算機之間進行通信的一種約定或一種方式,
通過 socket 這種約定,一臺計算機可以接收其他計算機的資料,也可以向其他計算機發送資料,
socket 的典型應用就是 Web 服務器和瀏覽器:瀏覽器獲取用戶輸入的 URL,向服務器發起請求,服務器分析接收到的 URL,將對應的網頁內容回傳給瀏覽器,瀏覽器再經過決議和渲染,就將文字、圖片、視頻等元素呈現給用戶,
例如我們每天瀏覽網頁、QQ 聊天、收發 email 等等,
二、socket 套接字的分類
這個世界上有很多種套接字,Internet 套接字、Unix套接字、X.25 套接字等,
這里我們討論 Internet 套接字,它是最具代表性的,也是最經典最常用的,我們經常提及的套接字,基本也都是指 Internet 套接字,
根據資料的傳輸方式,可以將 Internet 套接字分成兩種型別,
通過 socket() 函式創建連接時,必須告訴它使用哪種資料傳輸方式,
1、流格式套接字(SOCK_STREAM)
流格式套接字(Stream Sockets)也叫“面向連接的套接字”,在代碼中使用 SOCK_STREAM 表示,
SOCK_STREAM 是一種可靠的、雙向的通信資料流,資料可以準確無誤地到達另一臺計算機,如果損壞或丟失,可以重新發送,
SOCK_STREAM 有以下幾個特征:
- 資料在傳輸程序中不會消失;
- 資料是按照順序傳輸的;
- 資料的發送和接收不是同步的(有的說法也稱“不存在資料邊界”),
可以將 SOCK_STREAM 想象成一條傳輸帶,只要傳輸帶本身沒有問題(不會斷網),就能保證資料不丟失;同時,較晚傳送的資料不會先到達,較早傳送的資料不會晚到達,這就保證了資料是按照順序傳遞的,

為什么流格式套接字可以達到高質量的資料傳輸呢?這是因為它使用了 TCP 協議(The Transmission Control Protocol,傳輸控制協議),TCP 協議會控制你的資料按照順序到達并且沒有錯誤,
你也許見過 TCP,是因為你經常聽說“TCP/IP”,TCP 用來確保資料的正確性,IP(Internet Protocol,網路協議)用來控制資料如何從源頭到達目的地,也就是常說的“路由”,
那么,“資料的發送和接收不同步”該如何理解呢?
假設傳輸帶傳送的是水果,接收者需要湊齊 100 個后才能裝袋,但是傳送帶可能把這 100 個水果分批傳送,比如第一批傳送 20 個,第二批傳送 50 個,第三批傳送 30 個,接收者不需要和傳送帶保持同步,只要根據自己的節奏來裝袋即可,不用管傳送帶傳送了幾批,也不用每到一批就裝袋一次,可以等到湊夠了 100 個水果再裝袋,
流格式套接字的內部有一個緩沖區(也就是字符陣列),通過 socket 傳輸的資料將保存到這個緩沖區,接收端在收到資料后并不一定立即讀取,只要資料不超過緩沖區的容量,接收端有可能在緩沖區被填滿以后一次性地讀取,也可能分成好幾次讀取,
也就是說,不管資料分幾次傳送過來,接收端只需要根據自己的要求讀取,不用非得在資料到達時立即讀取,傳送端有自己的節奏,接收端也有自己的節奏,它們是不一致的,
2、資料報格式套接字(SOCK_DGRAM)
資料報格式套接字(Datagram Sockets)也叫“無連接的套接字”,在代碼中使用 SOCK_DGRAM 表示,
計算機只管傳輸資料,不作資料校驗,如果資料在傳輸中損壞,或者沒有到達另一臺計算機,是沒有辦法補救的,也就是說,資料錯了就錯了,無法重傳,
因為資料報套接字所做的校驗作業少,所以在傳輸效率方面比流格式套接字要高,
可以將 SOCK_DGRAM 比喻成高速移動的摩托車快遞,它有以下特征:
- 強調快速傳輸而非傳輸順序;
- 傳輸的資料可能丟失也可能損毀;
- 限制每次傳輸的資料大小;
- 資料的發送和接收是同步的(也稱為“存在資料邊界”),
總之,資料報套接字是一種不可靠的、不按順序傳遞的、以追求速度為目的的套接字,
資料報套接字也使用 IP 協議作路由,但是它不使用 TCP 協議,而是使用 UDP 協議(User Datagram Protocol,用戶資料報協議),
QQ 視頻聊天和語音聊天就使用 SOCK_DGRAM 來傳輸資料,因為首先要保證通信的效率,盡量減小延遲,而資料的正確性是次要的,即使丟失很小的一部分資料,視頻和音頻也可以正常決議,最多出現噪點或雜音,不會對通信質量有實質的影響,
注意:SOCK_DGRAM 沒有想象中的糟糕,不會頻繁的丟失資料,資料錯誤只是小概率事件,
三、代碼方式創建socket
在 Python 中 使用socket 模塊的函式 socket 就可以完成:
import socket
socket.socket(AddressFamily, Type)
說明:
函式 socket.socket 創建一個 socket,該函式帶有兩個引數:
- Address Family:可以選擇 AF_INET(用于 Internet 行程間通信) 或者 AF_UNIX(用于同一臺機器行程間通信),實際作業中常用AF_INET
- Type:套接字型別,可以是 SOCK_STREAM(流式套接字,主要用于 TCP 協議)或者 SOCK_DGRAM(資料報套接字,主要用于 UDP 協議)
以下我們稍微簡略地用 python 表達下套接字的代碼寫法,
1、創建一個tcp socket(tcp套接字)
import socket
#創建tcp的套接字
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# ...這里是使用套接字的功能(省略)...
# 不用的時候,關閉套接字
s.close()
2、創建一個udp socket(udp套接字)
import socket
# 創建udp的套接字
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# ...這里是使用套接字的功能(省略)...
# 不用的時候,關閉套接字
s.close()
說明:
套接字使用流程與檔案的使用流程很類似,三部曲:創建套接字,使用套接字收/發資料,關閉套接字,

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/3023.html
標籤:Python
上一篇:Editor.md 二次開發-markdown在線編輯器
下一篇:Python一些坑
