linux編程----網絡通信(TCP)

1.TCP特點

1.面向數據流;

2.有連接通信;

3.安全可靠的通信方式;

4.機制復雜,網絡資源開銷大;

5.本質只能實現一對一的通信(可使用TCP的并發方式實現一對多通信);

2.TCP的三次握手與四次揮手

1.TCP的三次握手

TCP建立連接時,需要進行三次握手,以確保收發雙方通信之前都已就緒;

2.TCP的四次揮手

TCP斷開連接時,需要四次揮手,以確保斷開連接前雙方都以通信結束;

SYN:請求建立連接標志;

FIN:請求斷開連接標志;

ACK:響應報文標志位;

3.TCP的編程流程

int connect(int sockfd, const struct sockaddr *addr,
socklen_t addrlen);
功能:請求與服務端建立連接
參數:
sockfd:套接字
addr:要連接的服務端的地址信息
addrlen:服務端地址大小
返回值:
成功:0
失敗:-1

?ssize_t send(int sockfd, const void *buf, size_t len, int flags);
功能:發送網絡數據
參數:
sockfd:網絡套接字
buf:要發送的數據首地址
len:發送的字節數
flags:0 :按照默認方式發送
返回值:
成功:實際發送的字節數
失敗:-1

int listen(int sockfd, int backlog);
功能:監聽建立三次握手的客戶端
參數:
sockfd:監聽套接字
backlog:最大允許監聽的客戶端個數
返回值:
成功:0
失敗:-1

int accept(int socket, struct sockaddr *restrict address,
socklen_t *restrict address_len);
功能:接收建立三次握手的客戶端,并產生一個通訊套接字
參數:
socket:監聽套接字
address:客戶端的地址信息
address_len:客戶端地址長的指針
返回值:
成功:通訊套接字
失敗:-1


ssize_t recv(int sockfd, void *buf, size_t len, int flags);
功能:從網絡套接字上接收數據
參數:
sockfd:通訊套接字
buf:存放接收數據的首地址
len:期望接收到的字節數
flag : 0:默認方式接收(阻塞)
返回值:
成功:實際接收到的字節數
失敗:-1
對方斷開連接:0

4.TCP的粘包問題

TCP粘包問題:發送方應用層發送的多包數據,將來在接收方可能一次讀到,多包數據產生了粘連。

? ? ? 原因:
1. 發送方速度較快,TCP底層可能對多包數據進行重新組幀;
2. 接收方數據處理速度較慢,導致多包數據在接收緩沖區緩存,應用層讀時,一次將多包數據讀出。

? ? ?
解決粘包問題的常用方法:

1. ?調整發送速率
2. ?發送指定大小,將來接收方也接受指定大小。
結構體
注意:
1. 跨平臺之間的數據傳輸時,注意結構體對齊問題。
struct a
{
char a;
int b;
long c;
};
32bits平臺《--》64位平臺

? ? ? ? ?3. 應用層位發送的數據增加分隔符,利用分隔符解析
hello world\nhow are you\n

? ? ? ? ?4. 封裝自定義數據幀格式進行發送(協議),嚴格根據協議進行解析。

AA ?C0 ?00 00 00 F0 00 BB 10 A0 ?00 00 00 10 校驗 BB ?AA ?C0 ?00 00 00 F0 00 BB 10 A0 ?00 00 00 10 校驗 BB AA ?C0 ?00 00 00 F0 00 BB 10 A0 ?00 00 00 10 校驗 BB

幀頭:AA
幀尾:BB
有效數據長度:C0
有效數據:00 00 00 F0 00 BB 10 A0 ?00 00 00 10
校驗:
8位和校驗
16位和校驗
CRC校驗

5.代碼練習

1. tcp實現圖片的傳輸

//客戶端
#include <stdio.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h> /* superset of previous */
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>int main(int argc, char const *argv[])
{if(argc != 2){printf("./a.out <filename>\n");return -1;}int sockfd = socket(AF_INET, SOCK_STREAM, 0);if(sockfd < 0){perror("socket error");return -1;}struct sockaddr_in sockaddr;sockaddr.sin_family = AF_INET;sockaddr.sin_port = htons(50002);sockaddr.sin_addr.s_addr = inet_addr("192.168.0.139");int connfd = connect(sockfd, (struct sockaddr *)&sockaddr, sizeof(sockaddr));int fd = open(argv[1], O_RDONLY);if(fd < 0){perror("open error");return -1;}char buf[1024] = {0};int ret = 0;do{   ret = read(fd, buf, sizeof(buf));size_t conter = send(sockfd, buf, ret, 0);}while(ret > 0);close(fd);close(sockfd);return 0;
}//服務端
#include <stdio.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h> /* superset of previous */
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>int main(int argc, char const *argv[])
{if(argc != 2){printf("./a.out <filename>\n");return -1;}int sockfd = socket(AF_INET, SOCK_STREAM, 0);if(sockfd < 0){perror("socket error");return -1;}struct sockaddr_in sockaddr;sockaddr.sin_family = AF_INET;sockaddr.sin_port = htons(50002);sockaddr.sin_addr.s_addr = inet_addr("192.168.0.139");int ret = bind(sockfd, (struct sockaddr *)&sockaddr, sizeof(sockaddr));if(ret < 0){perror("bind error");return -1;}int n = listen(sockfd, 10);if(n < 0){perror("listen error");return -1;}struct sockaddr_in dest_sockaddr;socklen_t len = sizeof(dest_sockaddr);int connfd = accept(sockfd, (struct sockaddr *)&dest_sockaddr, &len);printf("[%s][%d] online\n", inet_ntoa(dest_sockaddr.sin_addr), ntohs(dest_sockaddr.sin_port));int fd = open(argv[1], O_WRONLY | O_TRUNC | O_CREAT, 0664);if(fd < 0){perror("open error");return -1;}char buf[1024] = {0};ssize_t cont = 0;do{   memset(buf, 0, sizeof(buf));cont = recv(connfd, buf, sizeof(buf), 0);write(fd, buf, cont);   }while(cont > 0);close(connfd);close(sockfd);return 0;
}

2. tcp實現全雙工聊天

//客戶端A:
#include <stdio.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h> /* superset of previous */
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>int sockfd = 0;
struct sockaddr_in sockaddr;int send_t()
{char buf[1024] = {0};while(1){   fgets(buf, sizeof(buf), stdin);buf[strlen(buf) - 1] = 0;size_t conter = send(sockfd, buf, strlen(buf), 0);if(conter > 0){printf("conter=%ld\n", conter);}if(conter < 0){perror("send error");return -1;}}close(sockfd);
}int recv_t()
{char buf[1024] = {0};do{   memset(buf, 0, sizeof(buf));ssize_t cont = recv(sockfd, buf, sizeof(buf), 0);if(cont > 0){printf("cont = %ld, buf = %s\n", cont, buf);}if(cont < 0){perror("send error");return -1;}  }while(1);close(sockfd);
}int main(int argc, char const *argv[])
{sockfd = socket(AF_INET, SOCK_STREAM, 0);if(sockfd < 0){perror("socket error");return -1;}sockaddr.sin_family = AF_INET;sockaddr.sin_port = htons(50001);sockaddr.sin_addr.s_addr = inet_addr("192.168.0.139");int connfd = connect(sockfd, (struct sockaddr *)&sockaddr, sizeof(sockaddr));//send_t();pid_t pid = fork();if(pid > 0){send_t(); }else if(pid == 0){recv_t(); }else{perror("fork error");return -1;}return 0;
}//服務端B
#include <stdio.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h> /* superset of previous */
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>struct sockaddr_in dest_sockaddr;
socklen_t len = sizeof(dest_sockaddr);
int sockfd = 0;
int connfd = 0;int recv_t()
{char buf[1024] = {0};do{   memset(buf, 0, sizeof(buf));ssize_t cont = recv(connfd, buf, sizeof(buf), 0);if(cont > 0){printf("cont = %ld, buf = %s\n", cont, buf);}if(cont < 0){perror("send error");return -1;}  }while(1);close(connfd);close(sockfd);
}int send_t()
{   char buf[1024] = {0};while(1){   fgets(buf, sizeof(buf), stdin);buf[strlen(buf) - 1] = 0;size_t conter = send(connfd, buf, strlen(buf), 0);if(conter > 0){printf("conter=%ld\n", conter);}if(conter < 0){perror("send error");return -1;}}close(connfd);close(sockfd);
}int main(int argc, char const *argv[])
{sockfd = socket(AF_INET, SOCK_STREAM, 0);if(sockfd < 0){perror("socket error");return -1;}struct sockaddr_in sockaddr;sockaddr.sin_family = AF_INET;sockaddr.sin_port = htons(50001);sockaddr.sin_addr.s_addr = inet_addr("192.168.0.139");int ret = bind(sockfd, (struct sockaddr *)&sockaddr, sizeof(sockaddr));if(ret < 0){perror("bind error");return -1;}int n = listen(sockfd, 10);if(n < 0){perror("listen error");return -1;}connfd = accept(sockfd, (struct sockaddr *)&dest_sockaddr, &len);printf("[%s][%d] online\n", inet_ntoa(dest_sockaddr.sin_addr), ntohs(dest_sockaddr.sin_port));//recv_t();pid_t pid = fork();if(pid > 0){recv_t();}else if(pid == 0){send_t();}else {perror("fork error");return -1;}return 0;
}

6.TCP頭部標志位

TCP報文頭部:

SYN:請求建立連接標志位;

ACK:響應標志位;

FIN:請求斷開連接標志位;

PSH:攜帶數據標志位,通知接收方從緩沖區讀取數據;

URG:緊急指針標志位;

RST:復位標志位/重置標志位;

7.TCP的其他機制

(1)確保安全可靠

1.三次握手與四次揮手機制
2.應答機制

sequence number:序列號;

Acknowledgment number:響應序列號;

TCP對于每一包數據都會有相應的應答;

發送數據時,序列號表示這包數據的起始編號,確認時,響應報文中的響應序列號為接收方收到的最后一個字節編號+1(即為期待下次希望收到數據的起始號,以確保數據的安全可靠)

3.超時重傳機制

當數據發出,在指定時間內(根據當前網絡狀態,TCP實時更新)未收到響應,此時認為數據丟失,則會重新發送這包數據;

4.滑動窗口機制

使用緩沖區實現TCP已發送未響應、準備發送的數據的緩存,確保數據重新傳時,可以找到相應數據;

(2)提高效率

1.延遲應答機制

連續發送數據的同時,等待對方的響應;

2.流量控制機制

結合TCP頭部窗口大小,動態調整接受速率;

3.捎帶應答機制

ACK可能與應用層數據同時發送;

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

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

相關文章

HTTP請求的執行流程

HTTP請求的執行流程是一個系統化的過程&#xff0c;涉及多個網絡協議和交互步驟。以下是完整的流程分解&#xff0c;結合關鍵技術和邏輯順序&#xff1a;&#x1f310; 一、連接準備階段??URL解析與初始化??客戶端&#xff08;瀏覽器/應用&#xff09;解析目標URL&#xff…

聯想win11筆記本音頻失效,顯示差號(x)

該博客可以解答 常見問題詳情 Win10系統安裝更新后右下角聲音出現紅叉&#xff0c;電腦也沒有聲音&#xff0c; 通過設備管理器查看“系統設備”發現“音頻部分“出現黃色感嘆號&#xff0c; 更新驅動、卸載驅動與第三方工具檢測安裝后重啟都不行。 故障原因 應該是用戶曾經…

elasticsearch 7.x elasticsearch 使用scroll滾動查詢中超時問題案例

一 問題 1.1 問題描述 2025-08-21 16:57:53.646 | WARN ||||||||||||| scheduling-1 | ElasticsearchRestTemplate | Could not clear scroll: Unable to parse response body; nested exception is ElasticsearchStatusException [Unable to parse response body]; nested: …

高并發內存池(1)-定長內存池

高并發內存池&#xff08;1&#xff09;-定長內存池 可以采用兩種方式&#xff1a; 方式1&#xff1a; template <size_t N>方式2&#xff1a; template <class T>獲取到T對象大小的內存池&#xff0c;更推薦使用方式二&#xff0c;因為可以動態靈活調整類型 需要的…

第三階段sql server數據-4:數據庫腳本生成,備份與還原,分離與附加操作的圖文步驟

1_生成數據庫腳本&#xff08;1&#xff09;在數據庫上右鍵選擇任務&#xff08;2&#xff09;選擇生成腳本&#xff08;3&#xff09;選擇下一步&#xff0c;如果下次不想顯示此頁面&#xff0c;可勾選不再顯示此頁&#xff08;4&#xff09;如果導出全部數據&#xff0c;選擇…

【C++闖關筆記】STL:string的學習和使用(萬字精講)

?系列文章目錄 第零篇&#xff1a;從C到C入門&#xff1a;C有而C語言沒有的基礎知識總結-CSDN博客 第一篇&#xff1a;【C闖關筆記】封裝①&#xff1a;類與對象-CSDN博客 第二篇&#xff1a;【C闖關筆記】封裝②&#xff1a;友元與模板-CSDN博客 第三篇&#xff1a;【C闖…

06 - spring security角色和權限設置

spring security角色和權限設置 文檔 00 - spring security框架使用01 - spring security自定義登錄頁面02 - spring security基于配置文件及內存的賬號密碼03 - spring security自定義登出頁面04 - spring security關閉csrf攻擊防御05 - spring security權限控制 角色和權限…

如何實現文檔處理全流程自動化?

在處理文本文檔、電子郵件、視頻音頻、社媒帖子等非結構化數據時&#xff0c;我們經常發現這些數據難以用傳統的數據庫表格進行存儲和管理&#xff0c;因為其沒有明確的結構和標準化的格式&#xff0c;因此&#xff0c;這類數據處理難度較大&#xff0c;當傳統“人眼Excel”模式…

Java Main無法初始化主類的原因與解決方法(VsCode工具)

個人操作 由于上傳git將target目錄也上傳了所以在本地刪除target之后再重新同步更新動作然后直接在vscode工具上run本地項目運行報錯&#xff0c;報錯信息如下 報錯信息分析原因1. 工具配置 用 VS Code 的“Run”運行按鈕時&#xff0c;是否會自動編譯&#xff0c;取決于你的 V…

Azure Kubernetes Service (AKS)

Overview AKS&#xff08;Azure Kubernetes Service&#xff09; 是 Microsoft Azure 提供的一種托管Kubernetes 服務&#xff0c;旨在簡化 Kubernetes 集群的部署、管理和操作。輕松運行和擴展基于容器的應用程序&#xff0c;而無需管理 Kubernetes 本身的基礎設施。 AKS與 …

基于SpringBoot的校園信息共享系統【2026最新】

作者&#xff1a;計算機學姐 開發技術&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源碼”。 專欄推薦&#xff1a;前后端分離項目源碼、SpringBoot項目源碼、Vue項目源碼、SSM項目源碼、微信小程序源碼 精品專欄&#xff1a;…

PyTorch API 3 - distributed

文章目錄分布式通信包 - torch.distributed后端支持PyTorch 內置的后端選擇哪個后端&#xff1f;常見環境變量選擇使用的網絡接口其他NCCL環境變量基礎概念初始化返回類型&#xff1a;boolTCP初始化共享文件系統初始化環境變量初始化方法初始化后操作關閉處理重新初始化組Devic…

【K8s】整體認識K8s之Docker篇

首先認識幾個名詞&#xff0c;Docker-ce是docker的社區版本&#xff0c;提供給各種構建、發布、運行容器的工具&#xff1b;docker-ce-cli是社區版本的命令行工具&#xff0c;與docker守護進程進行交互&#xff1b;containerd.io是docker運行時&#xff08;containerd&#xff…

【機器學習】7 Linear regression

本章目錄 7 Linear regression 217 7.1 Introduction 217 7.2 Model specification 217 7.3 Maximum likelihood estimation (least squares) 217 7.3.1 Derivation of the MLE 219 7.3.2 Geometric interpretation 220 7.3.3 Convexity 221 7.4 Robust linear regression * 2…

【衛星通信】超低碼率語音編碼ULBC:EnCodec神經音頻編解碼器架構深度解析

引言 EnCodec是由Meta AI提出的一種端到端神經音頻編解碼器架構&#xff0c;其核心目標是在保證音頻質量的前提下實現高壓縮比和低帶寬傳輸。該模型通過結合卷積神經網絡、殘差矢量量化&#xff08;Residual Vector Quantization, RVQ&#xff09;、多尺度對抗訓練以及Transfor…

08_正則表達式

第8課:正則表達式 課程目標 理解正則表達式的基本概念 掌握常用的正則表達式模式 學習Python中re模塊的使用 能夠編寫簡單的正則表達式 1. 正則表達式基礎 1.1 什么是正則表達式 正則表達式是一種用于匹配字符串模式的工具,可以用于搜索、替換和驗證文本。 1.2 基本語法 …

小迪安全v2023學習筆記(七十一講)—— Python安全反序列化反編譯格式化字符串安全

文章目錄前記WEB攻防——第七十一天Python安全&反序列化利用鏈&PYC文件反編譯&格式化字符串安全Python - PYC-反編譯文件出源碼介紹演示Python - 反序列化-調用鏈&魔術方法各類語言序列化和反序列化函數序列化和反序列化含義Python中常用的序列化/反序列化函數…

Linux->多線程2

目錄 本文說明&#xff1a; 一&#xff1a;線程互斥 1&#xff1a;缺乏互斥的搶票系統 2&#xff1a;搶票系統分析及概念回顧 3&#xff1a;互斥鎖 ①&#xff1a;相關接口 a&#xff1a;定義鎖 b&#xff1a;初始化鎖 c&#xff1a;加鎖 d&#xff1a;解鎖 e&#x…

[OpenVela] 音樂播放器1.0

code: https://github.com/lvy010/vela/tree/main/music_player OpenVela 音樂播放器 基于 OpenVela 系統的嵌入式音樂播放器&#xff0c;使用 LVGL 圖形庫開發&#xff0c;支持 Wi-Fi 連接和本地音頻播放。 &#x1f4cb; 目錄 項目簡介功能特性系統要求項目結構快速開始配…

學習 Android (十六) 學習 OpenCV (一)

學習 Android (十六) 學習 OpenCV (一) 在前幾個章節中&#xff0c;我們對 NDK 相關的開發有了一定的了解&#xff0c;所謂磨刀不誤砍柴工&#xff0c;有了這些基礎的知識儲備之后&#xff0c;我們可以來簡單上手一下 OpenCV 相關的知識&#xff0c;接下來跟隨作者一起來學習吧…