socket是什么?套接字是什么?


網絡編程就是編寫程序使兩台聯網的計算機相互交換數據。

那么,這兩台計算機之間用什么傳輸數據呢?首先你肯定先需要物理連接嘛。

在此基礎上,只需要考慮如何編寫數據傳輸程序。看似很麻煩,但實際上這點不用愁,因為操作系統已經提供了 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()

說明:

套接字使用流程與文件的使用流程很類似,三部曲:創建套接字,使用套接字收/發數據,關閉套接字。


編程的朝聖之路


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM