嵌入式學習的第三十四天-進程間通信-TCP

一、TCP

TCP?:?傳輸控制協議???傳輸層

1.?TCP特點

(1).面向連接,避免部分數據丟失
(2).安全、可靠
(3).面向字節流
(4).占用資源開銷大

2.TCP安全可靠機制

三次握手:指建立tcp連接時,需要客戶端和服務端總共發送三次報文確認連接。確保雙方均已做好? ? ? ? ? ? ? ? ? 收發數據的準備-----只能由客戶端發起

ACK:響應報文? ? SYN(TPC頭部標志位)請求建立連接? ? ?FIN請求斷開連接

四次揮手:斷開一個tcp連接,需要客戶端和服務端發送四個報文以確認斷開。確保斷開連接前收? ? ? ? ? ? ? ? ? ? 發數據均已完成 ,當服務端沒有數據需要發送,即不需要建立下一次連接時,服務端將? ? ? ? ? ? ? ? ? ? ? ? ? ACK和FIN一起發送出去,即三次揮手. 三次揮手不能確認服務端每一次有無下一次連接.

3.TCP

:服務端創建了兩個套接字,recv里接接收的是第二個套接字(通信套接字)

(1).socket

?socket(AF_INET,?SOCK_STREAM,?0);

(2).connect

? int?connect(int?sockfd,?const?struct?sockaddr?*addr,socklen_t?addrlen);
功能:發送三次握手鏈接請求
參數:sockfd:套接字文件描述符
addr:存放目的地址空間首地址
addrlen:目的地址長度
返回值: 成功返回0? 失敗返回-1

(3).send

?ssize_t?send(int?sockfd,?const?void?*buf,?size_t?len,?int?flags);
功能:發送數據
參數:sockfd:套接字文件描述符
buf:存放數據空間首地址
len:數據長度
flag:屬性默認為0?
返回值:成功返回發送字節數? ;? 失敗返回-1?

(4).recv

?ssize_t?recv(int?sockfd,?void?*buf,?size_t?len,?int?flags);
功能:接收數據?
參數:sockfd:套接字文件描述符
buf:存放數據空間首地址?
len:最多接收數據長度?
flags:接收屬性默認為0?
返回值:成功返回實際接收字節數? ;? 失敗返回-1 ;? 連接斷開返回0?

(5).bind

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

(6).listen

int?listen(int?sockfd,?int?backlog);
功能:監聽三次握手鏈接請求
參數:sockfd:套接字文件描述符
backlog:最多允許等待尚未處理的三次握手鏈接個數
返回值:成功返回0 ; 失敗返回-1?

(7).accept

? int?accept(int?sockfd,?struct?sockaddr?*addr,?socklen_t?*addrlen);
功能:處理三次握手等待隊列中的第一個請求并建立一個用來通信的新套接字
參數:sockfd:套接字文件描述符
addr:存放發送端IP地址空間首地址?
addrlen:想要接收的IP地址的長度?
返回值:成功返回新文件描述符(通訊套接字) ; 失敗返回-1?

4.?TCP報文頭

標志位:

(1).?URG:?緊急指針標志,?為1時表示緊急指針有效,?該報文應該優先傳送。
(2).?ACK:?確認應答標志
(3).?PSH:??表示發送數據,提示接收端從TCP接收緩沖區中讀走數據,為接收后續數據騰出空間
(4).?RST:?重置連接標志
(5).?SYN:?表示請求建立一個連接
(6).?FIN:?finish標志,?表示釋放連接

滑動窗口大小:是TCP流量控制得一個手段。目的是告訴對方,?本端得TCP接受緩沖區還能容納? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 多少字節得數據,
這樣對方就可以控制發送數據的速度,從而達到流量控制,16bit,2字節,因而窗口最大65535.

5.?TCP的機制

TCP復雜是因為它既要保證可靠性,同時又要盡可能的提高性能。

可靠性:

(1) 三次握手和四次揮手機制
(2)?確認應答:TCP將每個字節的數據都進行了編號,即為序列號。每一個ACK都帶有對應的確認 序列號,保證數據不丟失的按序到達
(3) 超時重傳:當發送端發送的數據在網絡中丟失時,在一定時間內沒有收到接收端的ACK,則發送端會重新發送丟失數據。
(4)流量控制:按照ACK中“窗口大小”字段控制發送端的發送速度

提高性能:

(1)滑動窗口(緩沖區):可以按照“窗口大小”,?一次發送多條后,?再等待應答。


(2)延遲應答:當接收方處理速度很快時,可以延遲發送ACK,此時"窗口大小"會自動增大
(3)捎帶應答:搭載應用層的響應報文發送ACK。

?6.?TCP粘包問題----面試題

TCP協議是面向字節流的協議,接收方不知道消息的界限,不知道一次提取多少數據,這就造成了粘包問題。

粘包問題出現的原因: (接受發送速率不匹配)

(1).?發送端:發送方發送數據過快,造成粘包;
(2).?接收端:不及時的接收緩沖區內的包,造成多個包接收。接收過慢.

避免粘包問題的方法:(usleep())

(1).?對于定長的包,發送固定大小字節的數據,保證每次都按固定大小讀取即可;//??結構體

? ? ?問題:1)結構體對齊問題(比如:指定按1字節對齊),不能放指針

? ? ? ? ? ? ?2)發送數據類型多樣化時,接收方難區分接受大小

(2).?對于變長的包,還可以在包和包之間使用明確的數據分隔符,這個分隔符是由程序員自己來定的,只要保證分隔符不和正文沖突即可。

eg:hello world\n how are you\n xxxx\n

應用層可以根據\n進行解析

(3).自定義應用層的協議幀

幀頭: AA 1字節

有效數據長度: len 1字節

幀尾: BB 1字節

校驗:8bits和校驗(1字節)? 16bits和校驗(2字節)? ? CRC校驗

二、練習?

1.使用tcp實現雙人聊天

//cli.c
#include "head.h"int init_tcp_cli(const char *ip, unsigned short port)
{int sockfd = socket(AF_INET, SOCK_STREAM, 0);if (sockfd < 0){perror("fail socket");return -1;}struct sockaddr_in seraddr;seraddr.sin_family = AF_INET;seraddr.sin_port = htons(port);seraddr.sin_addr.s_addr = inet_addr(ip);int ret = connect(sockfd, (struct sockaddr *)&seraddr, sizeof(seraddr));if (ret < 0){perror("fail connect");return -1;}return sockfd;
}void *send_msg(void *arg)
{char buff[1024] = {0};int sockfd = *((int *)arg);while (1){memset(buff, 0, sizeof(buff));fgets(buff ,sizeof(buff), stdin);send(sockfd, buff, strlen(buff), 0);}return NULL;
}void *recv_msg(void *arg)
{char buff[1024] = {0};int sockfd = *((int *)arg);while (1){memset(buff, 0, sizeof(buff));ssize_t size = recv(sockfd, buff, sizeof(buff), 0);if (size < 0){perror("fail recv");break;}else if (0 == size){printf("connect lost\n");break;}printf("B-->A: %s\n", buff);}return NULL;
}int main(int argc, const char *argv[])
{pthread_t tid[2];int sockfd = init_tcp_cli("192.168.1.162", 50000);if (sockfd < 0){return -1;}pthread_create(&tid[0], NULL, send_msg, &sockfd);pthread_create(&tid[1], NULL, recv_msg, &sockfd);pthread_join(tid[0], NULL);pthread_join(tid[1], NULL);close(sockfd);return 0;
}
//ser.c
#include "head.h"int init_tcp_ser(const char *ip, unsigned short port)
{int sockfd = socket(AF_INET, SOCK_STREAM, 0);if (sockfd < 0){perror("fail socket");return -1;}struct sockaddr_in seraddr;seraddr.sin_family = AF_INET;seraddr.sin_port = htons(port);seraddr.sin_addr.s_addr = inet_addr(ip);int ret = bind(sockfd, (struct sockaddr *)&seraddr, sizeof(seraddr));if (ret < 0){perror("fail bind");return -1;}ret = listen(sockfd, 10);if (ret < 0){perror("fail listen");return -1;}return sockfd;
}void *send_msg(void *arg)
{char buff[1024] = {0};int sockfd = *((int *)arg);while (1){memset(buff, 0, sizeof(buff));fgets(buff ,sizeof(buff), stdin);send(sockfd, buff, strlen(buff), 0);}return NULL;
}void *recv_msg(void *arg)
{char buff[1024] = {0};int connfd = *((int *)arg);while (1){memset(buff, 0, sizeof(buff));ssize_t size = recv(connfd, buff, sizeof(buff), 0);if (size < 0){perror("fail recv");break;}else if (0 == size){printf("connect lost\n");break;}printf("A-->B: %s\n", buff);}return NULL;
}int main(int argc, const char *argv[])
{pthread_t tid[2];int sockfd = init_tcp_ser("192.168.1.162", 50000);if (sockfd < 0){return -1;}int connfd = accept(sockfd, NULL, NULL);if (connfd < 0){perror("fail accpet");return -1;}pthread_create(&tid[0], NULL, send_msg, &connfd);pthread_create(&tid[1], NULL, recv_msg, &connfd);pthread_join(tid[0], NULL);pthread_join(tid[1], NULL);close(connfd);close(sockfd);return 0;
}
#ifndef __HEAD_H__
#define __HEAD_H__#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 <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>#endif

?2.使用tcp實現文件發送()

//cli.c
#include "head.h"int init_tcp_cli(const char *ip, unsigned short port)
{int sockfd = socket(AF_INET, SOCK_STREAM, 0);if (sockfd < 0){perror("fail socket");return -1;}struct sockaddr_in seraddr;seraddr.sin_family = AF_INET;seraddr.sin_port = htons(port);seraddr.sin_addr.s_addr = inet_addr(ip);int ret = connect(sockfd, (struct sockaddr *)&seraddr, sizeof(seraddr));if (ret < 0){perror("fail connect");return -1;}return sockfd;
}int send_file(int sockfd, const char *filename)
{send(sockfd, filename, strlen(filename), 0);usleep(10);int fd = open(filename, O_RDONLY);if (fd < 0){perror("fail open");return -1;}char buff[1024] = {0};while (1){ssize_t size = read(fd, buff, sizeof(buff));if (size <= 0){break;}send(sockfd, buff, size, 0);}close(fd);return 0;
}int main(int argc, const char *argv[])
{int sockfd = init_tcp_cli("192.168.1.162", 50000);if (sockfd < 0){return -1;}send_file(sockfd, "1.jpg");close(sockfd);return 0;
}
//ser.c
#include "head.h"int init_tcp_ser(const char *ip, unsigned short port)
{int sockfd = socket(AF_INET, SOCK_STREAM, 0);if (sockfd < 0){perror("fail socket");return -1;}struct sockaddr_in seraddr;seraddr.sin_family = AF_INET;seraddr.sin_port = htons(port);seraddr.sin_addr.s_addr = inet_addr(ip);int ret = bind(sockfd, (struct sockaddr *)&seraddr, sizeof(seraddr));if (ret < 0){perror("fail bind");return -1;}ret = listen(sockfd, 10);if (ret < 0){perror("fail listen");return -1;}return sockfd;
}int recv_file(int connfd)
{char buff[1024] = {0};char fileneme[1024] = {0};recv(connfd, fileneme, sizeof(fileneme), 0);printf("fileneme = %s\n", fileneme);int fd = open(fileneme, O_WRONLY | O_CREAT | O_TRUNC, 0664);if (fd < 0){perror("fail open");return -1;}while (1){ssize_t size = recv(connfd, buff, sizeof(buff), 0);if (size <= 0){break;}write(fd, buff, size);}close(fd);return 0;
}int main(int argc, const char *argv[])
{int sockfd = init_tcp_ser("192.168.1.162", 50000);if (sockfd < 0){return -1;}int connfd = accept(sockfd, NULL, NULL);if (connfd < 0){perror("fail accpet");return -1;}recv_file(connfd);close(connfd);close(sockfd);return 0;
}

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

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

相關文章

【爬蟲】06 - 自動化爬蟲selenium

自動化爬蟲selenium 文章目錄自動化爬蟲selenium一&#xff1a;Selenium簡介1&#xff1a;什么是selenium2&#xff1a;安裝準備二&#xff1a;元素定位1&#xff1a;id 定位2&#xff1a;name 定位3&#xff1a;class 定位4&#xff1a;tag 定位5&#xff1a;xpath 定位(最常用…

2025年中國移動鴻鵠大數據實訓營(大數據方向)kafka講解及實踐-第2次作業指導

書接上回&#xff0c;第二次作業比較容易解決&#xff0c;我問了ai&#xff0c;讓他對我進行指導&#xff0c;按照它提供的步驟&#xff0c;我完成了本次實驗&#xff0c;接下來我會標注出需要注意的細節&#xff0c;指導大家完成此次任務。 &#x1f3af; 一、作業目標 ??…

三十七、【高級特性篇】定時任務:基于 APScheduler 實現測試計劃的靈活調度

三十七、【高級特性篇】定時任務:基于 APScheduler 實現測試計劃的靈活調度 前言 準備工作 第一部分:后端實現 - `APScheduler` 集成與任務調度 1. 安裝 `django-apscheduler` 2. 配置 `django-apscheduler` 3. 數據庫遷移 4. 創建調度觸發函數 5. 啟動 APScheduler 調度器 6…

RabbitMQ--消息順序性

看本章之前強烈建議先去看博主的這篇博客 RabbitMQ--消費端單線程與多線程-CSDN博客 一、消息順序性概念 消息順序性是指消息在生產者發送的順序和消費者接收處理的順序保持一致。 二、RabbitMQ 順序性保證機制 情況順序保證情況備注單隊列&#xff0c;單消費者消息嚴格按發送順…

.net core接收對方傳遞的body體里的json并反序列化

1、首先我在通用程序里有一個可以接收對象型和數組型json串的反序列化方法public static async Task<Dictionary<string, string>> AllParameters(this HttpRequest request){Dictionary<string, string> parameters QueryParameters(request);request.Enab…

(10)機器學習小白入門 YOLOv:YOLOv8-cls 模型評估實操

YOLOv8-cls 模型評估實操 (1)機器學習小白入門YOLOv &#xff1a;從概念到實踐 (2)機器學習小白入門 YOLOv&#xff1a;從模塊優化到工程部署 (3)機器學習小白入門 YOLOv&#xff1a; 解鎖圖片分類新技能 (4)機器學習小白入門YOLOv &#xff1a;圖片標注實操手冊 (5)機器學習小…

Vue 腳手架基礎特性

一、ref屬性1.被用來給元素或子組件注冊引用信息&#xff08;id的替代者&#xff09;2.應用在html標簽上獲取的是真實DOM元素&#xff0c;用在組件標簽上是組件實例對象3.使用方式&#xff1a;(1).打標識&#xff1a;<h1 ref"xxx">...</h1> 或 <Schoo…

Ubuntu安裝k8s集群入門實踐-v1.31

準備3臺虛擬機 在自己電腦上使用virtualbox 開了3臺1核2G的Ubuntu虛擬機&#xff0c;你可以先安裝好一臺&#xff0c;安裝第一臺的時候配置臨時調高到2核4G&#xff0c;安裝速度會快很多&#xff0c;安裝完通過如下命令關閉桌面&#xff0c;能夠省內存占用&#xff0c;后面我們…

Word Press富文本控件的保存

新建富文本編輯器&#xff0c;并編寫save方法如下&#xff1a; edit方法&#xff1a; export default function Edit({ attributes, setAttributes }) {return (<><div { ...useBlockProps() }><RichTexttagNameponChange{ (value) > setAttributes({ noteCo…

【編程趣味游戲】:基于分支循環語句的猜數字、關機程序

&#x1f31f;菜鳥主頁&#xff1a;晨非辰的主頁 &#x1f440;學習專欄&#xff1a;《C語言學習》 &#x1f4aa;學習階段&#xff1a;C語言方向初學者 ?名言欣賞&#xff1a;"編程的核心是實踐&#xff0c;而非空談" 目錄 1. 游戲1--猜數字 1.1 rand函數 1.2 sr…

UE5 UI 控件切換器

文章目錄分類作用屬性分類 面板 作用 可以根據索引切換要顯示哪個子UI&#xff0c;可以擁有多個子物體&#xff0c;但是任何時間只能顯示一個 屬性 在這里指定要顯示的UI的索引

scikit-learn 包

文章目錄scikit-learn 包核心功能模塊案例其他用法**常用功能詳解****(1) 分類任務示例&#xff08;SVM&#xff09;****(2) 回歸任務示例&#xff08;線性回歸&#xff09;****(3) 聚類任務示例&#xff08;K-Means&#xff09;****(4) 特征工程&#xff08;PCA降維&#xff0…

Excel 將數據導入到SQLServer數據庫

一般系統上線前期都會導入期初數據&#xff0c;業務人員一般要求你提供一個Excel模板&#xff0c;業務人員根據要求整理數據。SQLServer管理工具是支持批量導入數據的&#xff0c;所以我們可以使用該工具導入期初。Excel格式 第一行為字段1、連接登入的數據庫并且選中你需要導入…

剪枝和N皇后在后端項目中的應用

剪枝算法&#xff08;Pruning Algorithm&#xff09; 生活比喻&#xff1a;就像修剪樹枝一樣&#xff0c;把那些明顯不會結果的枝條提前剪掉&#xff0c;節省養分。 在后端項目中的應用場景&#xff1a; 搜索優化&#xff1a;在商品搜索中&#xff0c;如果某個分類下沒有符合條…

cocos 2d游戲中多邊形碰撞器會觸發多次,怎么解決

子彈打到敵機 一發子彈擊中&#xff0c;碰撞回調多次執行 我碰撞組件原本是多邊形碰撞組件 PolygonCollider2D&#xff0c;我改成盒碰撞組件BoxCollider2D 就好了 用前端的節流方式。或者loading處理邏輯。我測試過了&#xff0c;是可以 本來就是多次啊,設計上貌似就是這樣的…

Kubernetes環境中GPU分配異常問題深度分析與解決方案

Kubernetes環境中GPU分配異常問題深度分析與解決方案 一、問題背景與核心矛盾 在基于Kubernetes的DeepStream應用部署中&#xff0c;GPU資源的獨占性分配是保障應用性能的關鍵。本文將圍繞一個典型的GPU分配異常問題展開分析&#xff1a;多個請求GPU的容器本應獨占各自的GPU&…

Django與模板

我叫補三補四&#xff0c;很高興見到大家&#xff0c;歡迎一起學習交流和進步今天來講一講視圖Django與模板文件工作流程模板引擎&#xff1a;主要參與模板渲染的系統。內容源&#xff1a;輸入的數據流。比較常見的有數據庫、XML文件和用戶請求這樣的網絡數據。模板&#xff1a…

日本上市IT企業|8月25日將在大連舉辦赴日it招聘會

株式會社GSD的核心戰略伙伴貝斯株式會社&#xff0c;將于2025年8月25日在大連香格里拉大酒店商務會議室隆重舉辦赴日技術人才專場招聘會。本次招聘會面向全國范圍內的優秀IT人才&#xff0c;旨在為貝斯株式會社東京本社長期發展招募優質的系統開發與管理人才。招聘計劃&#xf…

低功耗設計雙目協同畫面實現光學變焦內帶AI模型

低功耗設計延長續航&#xff0c;集成儲能模塊保障陰雨天氣下的鐵塔路線的安全一、智能感知與識別技術 多光譜融合監控結合可見光、紅外熱成像、激光補光等技術&#xff0c;實現全天候監測。例如&#xff0c;紅外熱成像可穿透雨霧監測山火隱患&#xff0c;激光補光技術則解決夜間…

datasophon下dolphinscheduler執行腳本出錯

執行hive腳本出錯&#xff1a; 錯誤消息&#xff1a; FAILED: RuntimeException Error loading hooks(hive.exec.post.hooks): java.lang.ClassNotFoundException: org.apache.atlas.hive.hook.HiveHookat java.net.URLClassLoader.findClass(URLClassLoader.java:387)at java.…