TCP網絡編程(一)—— 服務器端模式和客戶端模式

這篇文章將會編寫基本的服務器網絡程序,主要講解服務器端和客戶端代碼的原理,至于網絡名詞很具體的概念,例如什么是TCP協議,不會過多涉及。

首先介紹一下TCP網絡編程的兩種模式:服務器端和客戶端模式:

????????首先說明一下:黑色線代表狀態的轉換,紅色線表示的是數據的傳輸,read 和 write 之間的循環表示:例如讀取完數據,進入寫入的狀態,寫入完再進入讀取的狀態,一直循環,實現了服務器和客戶端之間的通信。


首先來解釋一下服務器端:

int socket(int domain, int type, int protocol)

socket()?表示創建一個套接字。套接字是網絡通信的基本數據結構,用于定義通信協議(如 TCP 或 UDP)和地址族(如 IPv4 或 IPv6)。通過套接字,服務器和客戶端可以在網絡上傳輸數據,可以把套接字理解為一個編程接口,利用套接字實現程序和網絡的連接,像是用戶層和傳輸層(TCP)中間的一個抽象層,有了套接字才可以向網絡發送數據。

傳入的內容是(協議族,套接字類型,默認協議(通常為0))
返回:成功返回套接字描述符,失敗返回-1?

int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)

bind() 表示將套接字綁定到一個特定的地址和端口。綁定的地址和端口標識服務器,使客戶端能夠找到并連接到該服務。只有套接字還不夠,我還要知道是哪個主機(IP)發送的,哪個應用程序(端口)發送的,端口可以理解為電腦通信的入口和出口。

傳入的內容是:(套接字描述符,地址結構體的地址,地址結構體大小)
返回:成功返回0,失敗返回-1。

int listen(int sockfd, int backlog)

listen()?表示將套接字轉換為監聽模式,并設置等待連接的隊列長度。當多個客戶端請求連接時,服務器會將這些請求加入隊列,按順序處理。

傳入的內容是(套接字描述符,隊列的長度)
返回:成功返回0,失敗返回-1。

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)

accept()?表示等待接受客戶端的連接請求,接收到請求,成功連接后,accept()?返回一個新的套接字,用于與該客戶端通信,而原始監聽套接字則繼續處理新的連接請求。

傳入的內容是:(套接字描述符,地址結構體的地址,地址結構體大小的地址)
返回:成功返回新的套接字描述符,失敗返回-1?

ssize_t read(int sockfd, void *buf, size_t count)

read()?表示從套接字描述符中讀取數據,用于接收客戶端發送的消息。讀取的數據存儲在提供的緩沖區中。

傳入的內容是:(套接字描述符,緩沖區指針(數組),要讀取的字節數)
返回:成功返回實際讀取的字節數,失敗返回-1。

ssize_t write(int sockfd, const void *buf, size_t count)

write()?表示向套接字描述符中寫入數據,用于向客戶端發送響應數據。

傳入的內容是:(套接字描述符,緩沖區指針(數組),要寫入的字節數)
返回:成功返回實際寫入的字節數,失敗返回-1。

int close(int sockfd)

close()表示關閉套接字描述符。

傳入的內容是:(套接字描述符)
返回:成功返回0,失敗返回-1。?


接著解釋一下客戶端的新出現的函數:

int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

connet()表示客戶端向服務器發起連接請求。客戶端告訴操作系統需要連接到哪個服務器的哪個端口。

傳入的內容是:(套接字描述符,地址結構體的地址,地址結構體大小)
返回:成功返回0,失敗返回-1。

看完這些,你會發現:套接字描述符和文件描述符很像,都可以根據描述進行寫入讀取和各種其他操作,其實,這就是UNIX系統和類UNIX系統(Linux系統)的抽象資源管理方式,通過整數來標識系統中的資源,使用統一的接口設計,“一切皆文件”。

看到這里,你一定有幾個問題:

1.為什么客戶端少了bind()和listen()的操作?

2.為什么connect操作指向了accept操作之后?

3.地址結構體的地址addr是個什么東西?

4.為什么有的函數傳addr大小,有的傳addr大小的地址?

1.對于服務器端來說,服務器需要綁定到固定的端口這樣客戶端才能知道它,對于客戶端來說,操作系統會在必要的時候分配臨時的本地端口和地址,不需要再綁定端口。

2.因為服務器端的accept函數是阻塞的,等待客戶端發起請求,當connect發送給服務器端請求之后,才會繼續進行后面的讀寫操作。

3.addr的類型如下:有兩個成員,分別是地址族,地址和端口信息,但是這不方便我們進行設置,所以一般采用 sockaddr_in 這個結構,最后在進行強制類型轉換得到sockaddr,注意這兩個結構體類型大小是一樣的,只是結構不一樣。

struct sockaddr {sa_family_t sa_family;    // 地址族,例如 AF_INET(IPv4)或 AF_INET6(IPv6)char sa_data[14];         // 地址和端口信息
};

下面是sockaddr_in結構體類型,可以清楚地看到每個成員的含義:

struct sockaddr_in {sa_family_t sin_family;   // 地址族,通常為 AF_INET(IPv4)uint16_t sin_port;        // 端口號(16 位),以網絡字節序表示struct in_addr sin_addr;  // IP 地址(32 位)char sin_zero[8];         // 保留字段,填充用
};

4.可以看到accept函數的addrlen參數是 addr 大小(變量)的地址,但是connect和bind函數的addrlen參數是 addr 大小(變量)本身,這是因為accept不知道調用者提供的 addr 緩沖區的大小可能是IPv4可能是IPv6,所以需要地址地址。

我猜測可能和TCP的三次握手或者accept返回新的套接字或者客戶端分配動態端口有關系,而connect和bind函數都是用已知的套接字進行操作,所以不會進行addr大小的改變,所以可以直接傳值。

這就是TCP編程的兩種模式,從下篇文章開始,我們將學習如何編寫服務器端和客戶端的代碼。

這就是文章的所有內容了,希望對你有所幫助,如有錯誤歡迎指出。

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

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

相關文章

C# 設計模式(行為型模式):責任鏈模式

C# 設計模式(行為型模式):責任鏈模式 責任鏈模式(Chain of Responsibility Pattern)是一種行為型設計模式,用于讓多個對象有機會處理同一個請求,避免請求發送者與接收者之間的耦合。它通過將請…

在K8S中,如何部署kubesphere?

在Kubernetes集群中,對于一些基礎能力較弱的群體來說K8S控制面板操作存在一定的難度,此時kubesphere可以有效的解決這類難題。以下是部署kubesphere的操作步驟: 操作部署: 1. 部署nfs共享存儲目錄 yum -y install nfs-server e…

CSS系列(43)-- Anchor Positioning詳解

前端技術探索系列:CSS Anchor Positioning詳解 🎯 致讀者:探索智能定位的藝術 👋 前端開發者們, 今天我們將深入探討 CSS Anchor Positioning,這個強大的元素定位特性。 基礎概念 🚀 錨點設…

Python判別不同平臺操作系統調用相應的動態庫讀寫NFC

本示例使用的發卡器:https://item.taobao.com/item.htm?spma21dvs.23580594.0.0.52de2c1bV0E4YV&ftt&id615391857885 import sys import struct # struct的pack函數把任意數據類型變成字符串 import ctypes # 調用DLL動態庫要有這個引用if sys.platform…

樹莓派之旅-第一天 系統的燒錄和設置

自言自語: 在此記錄一下樹莓派的玩法。以后有錢了買點來玩啊草 系統的安裝燒錄 系統下載 樹莓派官網:https://www.raspberrypi.com/ 首頁點擊SoftWare進入OS下載頁面 這里是安裝工具:安裝工具負責將系統鏡像安裝到sd卡中 點擊下載符合自己…

商用車自動駕駛,迎來大規模量產「臨界點」?

商用車自動駕駛,正迎來新的行業拐點。 今年初,交通部公開發布AEB系統運營車輛標配征求意見稿,首次將法規限制條件全面放開,有望推動商用車AEB全面標配,為開放場景的商用車智能駕駛市場加了一把火。 另外,…

人工智能及深度學習的一些題目

1、一個含有2個隱藏層的多層感知機(MLP),神經元個數都為20,輸入和輸出節點分別由8和5個節點,這個網絡有多少權重值? 答:在MLP中,權重是連接神經元的參數,每個連接都有一…

Solon 加入 GitCode:助力國產 Java 應用開發新飛躍

在當今數字化快速發展的時代,Java 應用開發框架不斷演進,開發者們始終在尋找更快、更小、更簡單的解決方案。近期,Solon 正式加入 GitCode,為廣大 Java 開發者帶來全新的開發體驗,尤其是在國產應用開發進程中&#xff…

VScode 只能運行c,運行不了c++的解決問題

原文鏈接:Vscode只能運行c,運行不了c的解決方法 VScode 只能運行c,運行不了c,怎么回事呢,解決問題: 在tasks.json中加上“"-lstdc"”, 這樣之后 要重啟VScode,點擊鏈接…

Ansible Jinja2 語法簡介及使用

1、Jinja2 介紹 Jinja2 是基于 python 的模板引擎,功能比較類似于 PHP 的 smarty,J2ee 的 Freemarker和velocity。它能完全支持unicode,并具有集成的沙箱執行環境,應用廣泛。 jinja2使用BSD授權 Jinja2的語法是由 variables(變量…

SpringCloud系列教程:微服務的未來 (五)枚舉處理器、JSON處理器、分頁插件實現

在現代 Java 開發中,我們常常需要處理各種通用的功能和需求,諸如枚舉的處理、JSON 數據處理,以及分頁查詢等。這些功能雖然看似簡單,但在實際開發中往往涉及到許多細節和優化。為了提高開發效率、減少重復代碼的編寫,我…

游戲引擎學習第69天

回顧碰撞響應時我們停留的位置 從昨天的討論開始,我們正準備處理碰撞響應的復雜性。具體來說,我們討論的是,當兩個實體在屏幕上發生碰撞時,如何回應這種情況。碰撞本身并不復雜,但要處理其后的反應和規則則更具挑戰性…

【Linux】信號處理

一、Linux系統信號 1、常見的系統信號 常見的Linux系統信號 信號值描述1SIGHUP掛起(hang up)進程2SIGINT中斷進(interrupt)程3SIGQUIT停止(stop)進程9SIGKILL無條件終止(terminate)…

開源模型應用落地-qwen2-7b-instruct-LoRA微調-Axolotl-單機多卡-RTX 4090雙卡(七)

一、前言 本篇文章將使用Axolotl去高效微調QWen2系列模型,通過閱讀本文,您將能夠更好地掌握這些關鍵技術,理解其中的關鍵技術要點,并應用于自己的項目中。 二、術語介紹 2.1. LoRA微調 LoRA (Low-Rank Adaptation) 用于微調大型語言模型 (LLM)。 是一種有效的自適應策略,…

數據結構與算法學習筆記----快速冪

數據結構與算法學習筆記----快速冪 author: 明月清了個風 first publish time: 2025.1.2 ps??快速冪的兩道模版題,快速冪,乘法逆元,費馬小定理 Acwing 875. 快速冪 [原題鏈接](875. 快速冪 - AcWing題庫) 給定 n n n組 a i , b i , p i…

爬蟲代碼中如何添加異常處理?

在編寫爬蟲代碼時,添加異常處理是非常重要的一步,因為它可以幫助我們處理網絡請求中可能出現的各種問題,比如網絡連接錯誤、超時、解析錯誤等。以下是如何在Python爬蟲代碼中添加異常處理的示例: import requests from bs4 impor…

MAC環境安裝(卸載)軟件

MAC環境安裝(卸載)軟件 jdknode安裝node,并實現不同版本的切換背景 卸載node從node官網下載pkg安裝的node卸載用 homebrew 安裝的node如果你感覺刪的不夠干凈,可以再細分刪除驗證刪除結果 jdk 1.下載jdk 先去官網下載自己需要的版…

本地LLM部署--llama.cpp

–圖源GitHub項目主頁 概述 llama.cpp是以一個開源項目(GitHub主頁:llamma.cpp),也是本地化部署LLM模型的方式之一,除了自身能夠作為工具直接運行模型文件,也能夠被其他軟件或框架進行調用進行集成。 其…

uniapp中使用ruoyiPlus中的加密使用(crypto-js)

package.json中添加 "crypto-js": "^4.2.0", "jsencrypt": "^3.3.2",但是vue2中使用 import CryptoJS from cryptojs; 這一步就會報錯 參照 參照這里:vue2使用CryptoJS實現信息加解密 根目錄下的js文檔中新增一個AESwork.…

go項目使用gentool生成model的gen.go問題

Gen Tool 是一個沒有依賴關系的二進制文件,可以用來從數據庫生成結構。 使用方法: go install gorm.io/gen/tools/gentoollatest在項目根目錄,執行連接的數據庫中指定某幾張表結構生成數據庫model層 gentool -dsn "root:123456tcp(localhost:330…