計算機網絡套接字知識(非常詳細)從零基礎入門到精通

本節重點

  • 認識IP地址, 端口號, 網絡字節序等網絡編程中的基本概念;

  • 學習socket api的基本用法;

一、預備知識

1.理解源IP地址和目的IP地址

?在IP數據包頭部中,有兩個IP地址,分別叫做源IP地址和目的IP地址。

思考: 我們光有IP地址就可以完成通信了嘛?想象一下發qq消息的例子,有了IP地址能夠把消息發送到對方的機器上,但是還需要有一個其他的標識來區分出,這個數據要給哪個程序進行解析,此時就需要我們的目的IP地址。

2.認識端口號

在進行網絡通信的時候,是不是我們的兩臺機器在進行通信呢?本質是應用層在通信

幾乎任何層的協議,都要在報頭中提供,決定將自己的有效載荷交付給上層的哪一個協議的能力,怎么做到的呢?端口號(port)是傳輸層協議的內容.

  • 端口號是一個2字節16位的整數;
  • 端口號用來標識一個進程,告訴操作系統,當前的這個數據要交給哪一個進程來處理;
  • IP地址 + 端口號能夠標識網絡上的某一臺主機的某一個進程;
  • 一個端口號只能被一個進程占用.

3.理解 "端口號" 和 "進程ID"

我們之前在學習系統編程的時候,學習了 pid 表示唯一一個進程;此處我們的端口號也是唯一表示一個進程,那么這兩者之間是怎樣的關系?

?另外,一個進程可以綁定多個端口號;但是一個端口號不能被多個進程綁定。

4.理解源端口號和目的端口號

傳輸層協議(TCP和UDP)的數據段中有兩個端口號, 分別叫做源端口號和目的端口號. 就是在描述 "數據是誰發的, 要發給誰"。

socket通信本質上就是兩個進程之間在進行通信,只不過這里是跨網絡的進程間通信。比如看QQ和刷抖音的動作,實際就是手機上的QQ進程和抖音進程在和對端服務器主機上的QQ服務進程和抖音服務進程之間在進行通信。因此進程間通信的方式除了管道、消息隊列、信號量、共享內存等方式外,還有套接字,只不過前者是不跨網絡的,而后者是跨網絡的。

?理解socket這個名字

socket在英文上有“插座”的意思,插座上有不同規格的插孔,我們將插頭插入到對應的插孔當中就能夠實現電流的傳輸。在進行網絡通信時,客戶端就相當于插頭,服務端就相當于一個插座,但服務端上可能會有多個不同的服務進程(多個插孔),因此當我們在訪問服務時需要指明服務進程的端口號(對應規格的插孔),才能享受對應服務進程的服務。

5.認識TCP協議和UDP協議

此處我們先對TCP(Transmission Control Protocol 傳輸控制協議)有一個直觀的認識; 后面我們再詳細討論TCP的一 些細節問題.

  • 傳輸層協議
  • 有連接
  • 可靠傳輸
  • 面向字節流

此處我們也是對UDP(User Datagram Protocol 用戶數據報協議)有一個直觀的認識; 后面再詳細討論.

  • 傳輸層協議
  • 無連接
  • 不可靠傳輸
  • 面向數據報

TCP協議是一種可靠的傳輸協議,使用TCP協議能夠在一定程度上保證數據傳輸時的可靠性,而UDP協議是一種不可靠的傳輸協議,UDP協議的存在有什么意義?

首先,可靠是需要我們做更多的工作的,TCP協議雖然是一種可靠的傳輸協議,但這一定意味著TCP協議在底層需要做更多的工作,因此TCP協議底層的實現是比較復雜的,我們不能只看到TCP協議面向連接可靠這一個特點,我們也要能看到TCP協議對應的缺點。同樣的,UDP協議雖然是一種不可靠的傳輸協議,但這一定意味著UDP協議在底層不需要做過多的工作,因此UDP協議底層的實現一定比TCP協議要簡單,UDP協議雖然不可靠,但是它能夠快速的將數據發送給對方,雖然在數據在傳輸的過程中可能會出錯。

6.網絡字節序

我們已經知道,內存中的多字節數據相對于內存地址有大端和小端之分, 磁盤文件中的多字節數據相對于文件中的偏 移地址也有大端小端之分, 網絡數據流同樣有大端小端之分. 那么如何定義網絡數據流的地址呢?

  • 發送主機通常將發送緩沖區中的數據按內存地址從低到高的順序發出;
  • 接收主機把從網絡上接到的字節依次保存在接收緩沖區中,也是按內存地址從低到高的順序保存;
  • 因此,網絡數據流的地址應這樣規定:先發出的數據是低地址,后發出的數據是高地址.
  • TCP/IP協議規定,網絡數據流應采用大端字節序,即低地址高字節.
  • 不管這臺主機是大端機還是小端機, 都會按照這個TCP/IP規定的網絡字節序數將數據據;來發送/接收
  • 如果當前發送主機是小端, 就需要先轉成大端; 否則就忽略, 直接發送即可;

為使網絡程序具有可移植性,使同樣的C代碼在大端和小端計算機上編譯后都能正常運行,可以調用以下庫函數做網絡 字節序和主機字節序的轉換。

  • 這些函數名很好記,h表示host,n表示network,l表示32位長整數,s表示16位短整數。
  • 例如htonl表示將32位的長整數從主機字節序轉換為網絡字節序,例如將IP地址轉換后準備發送。
  • 如果主機是小端字節序,這些函數將參數做相應的大小端轉換然后返回;
  • 如果主機是大端字節序,這些函數不做轉換,將參數原封不動地

二、socket編程接口

1.socket 常見API

// 創建 socket 文件描述符 (TCP/UDP, 客戶端 + 服務器)
int socket(int domain, int type, int protocol);// 綁定端口號 (TCP/UDP, 服務器) 
int bind(int socket, const struct sockaddr *address,socklen_t address_len);// 開始監聽socket (TCP, 服務器)
int listen(int socket, int backlog);// 接收請求 (TCP, 服務器)
int accept(int socket, struct sockaddr* address,socklen_t* address_len);// 建立連接 (TCP, 客戶端)
int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);

2.sockaddr結構

socket API是一層抽象的網絡編程接口,適用于各種底層網絡協議,如IPv4、IPv6,以及后面要講的UNIX Domain Socket. 然而, 各種網絡協議的地址格式并不相同.

為什么沒有用void*代替struct sockaddr*類型?

我們可以將這些函數的struct sockaddr*參數類型改為void*,此時在函數內部也可以直接指定提取頭部的16個比特位進行識別,最終也能夠判斷是需要進行網絡通信還是本地通信,那為什么還要設計出sockaddr這樣的結構呢?實際在設計這一套網絡接口的時候C語言還不支持void*,于是就設計出了sockaddr這樣的解決方案。并且在C語言支持了void*之后也沒有將它改回來,因為這些接口是系統接口,系統接口是所有上層軟件接口的基石,系統接口是不能輕易更改的,否則引發的后果是不可想的,這也就是為什么現在依舊保留sockaddr結構的原因。

  • Pv4和IPv6的地址格式定義在netinet/in.h中,IPv4地址用sockaddr_in結構體表示,包括16位地址類型, 16位端口號和32位IP地址.
  • IPv4、IPv6地址類型分別定義為常數AF_INET、AF_INET6. 這樣,只要取得某種sockaddr結構體的首地址,不需要知道具體是哪種類型的sockaddr結構體,就可以根據地址類型字段確定結構體中的內容.
  • socket API可以都用struct sockaddr *類型表示, 在使用的時候需要強制轉化成sockaddr_in; 這樣的好處是程序的通用性, 可以接收IPv4, IPv6, 以及UNIX Domain Socket各種類型的sockaddr結構體指針做為參數;

?sockaddr 結構

?sockaddr_in 結構

雖然socket api的接口是sockaddr, 但是我們真正在基于IPv4編程時, 使用的數據結構是sockaddr_in; 這個結構里主要有三部分信息: 地址類型,端口號,IP地址,可是我們怎么沒看到套接字的域呢?

這里使用了我們的"##",我們來回憶一下它的用法

所以上面定義的宏傳入的參數是sin_,然后宏里面使用了"##"拼接family,這樣就看到了我們的套接字的域。

?in_addr結構

可以看到,struct sockaddr_in當中的成員如下:

  • sin_family:表示協議家族。
  • sin_port:表示端口號,是一個16位的整數。
  • sin_addr:表示IP地址,是一個32位的整數。

in_addr用來表示一個IPv4的IP地址. 其實就是一個32位的整數。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/14755.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/14755.shtml
英文地址,請注明出處:http://en.pswp.cn/web/14755.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Kotlin Flow應用舉例,launchIn 和collect用法及區別

launchIn 和 collect 都可以用于處理 MutableStateFlow<Message> 消息流&#xff0c;但它們有不同的用途和使用場景。 collect 用于在協程中收集消息流的最新值。它會一直監聽消息流&#xff0c;并在每次消息流的值發生變化時執行指定的代碼塊。 launchIn 用于在協程作…

【30天精通Prometheus:一站式監控實戰指南】第7天:postgres_exporter從入門到實戰:安裝、配置詳解與生產環境搭建指南,超詳細

親愛的讀者們&#x1f44b; ??歡迎加入【30天精通Prometheus】專欄&#xff01;&#x1f4da; 在這里&#xff0c;我們將探索Prometheus的強大功能&#xff0c;并將其應用于實際監控中。這個專欄都將為你提供寶貴的實戰經驗。&#x1f680; ??Prometheus是云原生和DevOps的…

Java基礎之異常(簡單易懂)

異常 1.JAVA異常體系 &#xff08;1&#xff09;Throwable類(表示可拋)是所有異常和錯誤的超類&#xff0c;兩個直接子類為Error和Exception,分別表示錯誤和異常;其中異常類Exception又分為運行時異常和非運行時異常&#xff0c;這兩個異常有很大區別&#xff0c;運行時異常也…

代碼隨想錄算法訓練營第三十一天| 貪心算法理論基礎、LeetCode455.分發餅干、LeetCode376. 擺動序列 、LeetCode53. 最大子序和

貪心算法理論基礎&#xff1a; 貪心算法沒有類似遞歸、回溯的套路。主要的思想可以理解為&#xff1a;用局部最優找全局最優。 #LeetCode 455. Assign Cookies #LeetCode 455. 視頻講解&#xff1a;貪心算法&#xff0c;你想先喂哪個小孩&#xff1f;| LeetCode&#xff1a;4…

魯教版六年級數學下冊-筆記

文章目錄 第五章 基本平面圖形1 線段、射線、直線2 比較線段的長短3 角4 角的比較5 多邊形和圓的初步認識第六章 整式的乘除1 同底數冪的乘法2 冪的乘方與積的乘方3 同底數冪的除法4 零指數冪與負整數指數冪5 整式的乘法6 平方差公式7 完全平方公式8 整式的除法 第七章 相交線與…

全域運營是割韭菜嗎?常見套路有哪些?

隨著全域運營賽道的全面開啟&#xff0c;全域運營服務商和全域運營系統的數量迅速增加&#xff0c;持續激發賽道活力的同時&#xff0c;也讓一些試圖用全域運營割韭菜的人有了可趁之機。 值得慶幸的是&#xff0c;由于當前全域運營賽道剛興起不久&#xff0c;因此&#xff0c;割…

Python | Leetcode Python題解之第110題平衡二叉樹

題目&#xff1a; 題解&#xff1a; class Solution:def isBalanced(self, root: TreeNode) -> bool:def height(root: TreeNode) -> int:if not root:return 0leftHeight height(root.left)rightHeight height(root.right)if leftHeight -1 or rightHeight -1 or a…

C++青少年簡明教程:If選擇語句

C青少年簡明教程&#xff1a;If選擇語句 C中選擇語句的語法是&#xff1a; if (條件) { 條件成立時需要執行的語句... } [else { 條件不成立時需要執行的語句... }] 說明&#xff1a; if后面使用一個括號&#xff0c;括號里是條件——關系表達式。 所謂的關系表達式就是判…

5.24學習記錄

[FSCTF 2023]ez_php2 比較簡單的pop鏈 <?php highlight_file(__file__); Class Rd{public $ending;public $cl;public $poc;public function __destruct(){echo "All matters have concluded";die($this->ending);}public function __call($name, $arg){for…

E1載波:一種2.048Mbps速率的PCM載波

E1載波的基本幀由32個子信道組成 幀長為256個bit,分為32個相等時隙&#xff0c;一個時隙為8個bit。256/328 時隙的編號為CH0~CH31 全幀包含256位,且每一幀用 125us時間傳送 E1載波支持的數據傳輸效率為2.048Mbps&#xff0c;用PCM編碼&#xff08;即 256bit/125us2.048Mbps…

Android 一個activity對應多個window

Android 一個activity對應多個window Android Activity 對應多個Window&#xff0c;Activity是應用程序的重要組成部分&#xff0c;在程序中的一個屏幕界面&#xff0c;用戶可以進行交互操作。在Android應用程序中&#xff0c;Activity對應著一個Window&#xff0c;一個Activi…

微信小程序源碼-基于Java后端的小區租拼車管理信息系統畢業設計(附源碼+演示錄像+LW)

大家好&#xff01;我是程序員一帆&#xff0c;感謝您閱讀本文&#xff0c;歡迎一鍵三連哦。 &#x1f49e;當前專欄&#xff1a;微信小程序畢業設計 精彩專欄推薦&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f380; Python畢業設…

洗完咖啡杯的最早時間

題目描述&#xff1a;給定一個數組arr&#xff0c;arr[i]代表第i號咖啡機泡一杯咖啡的時間&#xff0c;給定一個正數N&#xff0c;表示N個人在等著咖啡機&#xff0c;每臺咖啡機只能一個一個的泡咖啡&#xff0c;其次&#xff0c;只有一臺咖啡機可以洗杯子&#xff0c;一次只能…

1.OLED

1.基礎知識

kotlin重復類編譯報錯解決

Duplicate class org.jetbrains.annotations.TestOnly found in modules annotations-12.0 (com.intellij:annotations:12.0) and annotations-13.0 (org.jetbrains:annotations:13.0) Go to the documentation to learn how to <a href"d.android.com/r/tools 參考鏈…

網絡拓撲—DHCP服務配置

文章目錄 DHCP服務搭建相關配置細節前提安裝DHCP服務 DHCP服務搭建 相關配置細節前提 系統&#xff1a;Windows Server 2003 IP網段&#xff1a;10.0.0.0/24 三臺機子&#xff1a; 普通PC機 DHCP服務器 路由器&#xff08;兩塊網卡&#xff0c;連接內外網&#xff09; //注…

覆蓋索引與復合索引 小記

表 t_1 有一個復合索引 (user_id,create_time) 執行以下SQL SELECT COUNT(1) FROM t_1 WHERE create_time > 2024-01-10 AND create_time < 2024-05-25 ;看似不滿足復合索引最左前綴的條件,但依然會使用復合索引(user_id,create_time), 滿足覆蓋索引. 但如果是執行以…

【Unity】Unity項目轉抖音小游戲(三)資源分包,抖音云CDN

業務需求&#xff0c;開始接觸一下抖音小游戲相關的內容&#xff0c;開發過程中記錄一下流程。 使用資源分包可以優化游戲啟動速度&#xff0c;是抖音小游戲推薦的一種方式&#xff0c;抖音云也提供存放資源的CDN服務 抖音云官方文檔&#xff1a;https://developer.open-douyi…

基于灰狼優化算法優化支持向量機(GWO-SVM)時序預測

代碼原理及流程 基于灰狼優化算法優化支持向量機&#xff08;GWO-SVM&#xff09;的時序預測代碼的原理和流程如下&#xff1a; 1. **數據準備**&#xff1a;準備時序預測的數據集&#xff0c;將數據集按照時間順序劃分為訓練集和測試集。 2. **初始化灰狼群體和SVM模型參數…

LeetCode 47.全排列 II

LeetCode 47.全排列 II 1、題目 題目鏈接&#xff1a;47. 全排列 II 給定一個可包含重復數字的序列 nums &#xff0c;按任意順序 返回所有不重復的全排列。 示例 1&#xff1a; 輸入&#xff1a;nums [1,1,2] 輸出&#xff1a; [[1,1,2],[1,2,1],[2,1,1]]示例 2&#xff…