嵌入式LINUX——————网络TCP

一、TCP连接

1.TCP特点:

(1)面向链接

(2)面向字节流

(3)安全可靠的传输协议,因为会先建立连接

(4)占用资源开销大,效率低,实时性不佳,机制复杂

2.安全可靠机制

(1)三次握手:【客户端发起】
指建立tcp连接时,需要客户端和服务端总共发送三次报文确认连接。(确保双方都已经 做好收发数据的准备)

        ACK:响应报文

        STN:请求建立一个连接


(2)四次挥手:【两端都可发起】
断开一个tcp连接,需要客户端和服务端发送四个报文以确认断开。(确保断开前双方都已经收发完毕)

FIN:finish标志,表示释放连接

(3) 应答机制

每一个tcp头部有个序列号和确认应答号,TCP给每一抱会有一个序列号,发送方会把第一个编号给序号,在接受方应答的时候,会把确认序列号置最后一个编号的下一个编号回应

通过序列号和确定序列号来确定收发的

(4)超时重传机制

3.编程

(1)socket 

(2)connect

(1)功能: 发送三次握手链接请求
(2)参数:
sockfd:套接字文件描述符
addr:存放目的地址空间首地址
addrlen:目的地址长度
(3)返回值:
成功返回0 
失败返回-1

(3)send

(1)功能:发送数据
(2)参数:
sockfd:套接字文件描述符
buf:存放数据空间首地址
len:数据长度
(3)返回值:
成功返回发送字节数
失败返回-1

(4)recv     

(1)功能:接收数据 
(2)参数:
sockfd:套接字文件描述符
buf:存放数据空间首地址 
len:最多接收数据长度 
flags:接收属性默认为0 
(3)返回值:
成功返回实际接收字节数
失败返回-1 
对方连接断开,直接返回,不在阻塞,没有数据返回0; 

(5)bind

(6)listen

(1)功能:监听三次握手链接请求
(2)参数:
sockfd:套接字文件描述符
backlog:最多允许等待尚未处理的三次握手链接个数
(3)返回值:
成功返回0 
失败返回-1 

(7)accept

   

(1)功能::处理三次握手等待队列中的第一个请求并建立一个用来通信的新套接字
(2)参数:
sockfd:套接字文件描述符
addr:存放发送端IP地址空间首地址 
addrlen:想要接收的IP地址的长度 
(3) 返回值:
成功返通讯套接字
失败返回-1 

4.提高效率

(1)延迟应答

(2)捎带应答

(3)流量控制机制

发送端根据窗口的数据大小,去动态控制发送端的数据;0--65535,接收端根据自己的能力,去调整窗口的大小,65535的时候,接受端处理能力最强,发送端可以发快一点。

(4)滑动窗口

        滑动窗口大小:是TCP流量控制得一个手段。目的是告诉对方, 本端得TCP接受缓冲区还能容纳多少字节得数据,这样对方就可以控制发送数据的速度,从而达到流量控制,16bit,因而窗口最大65535.

        本质是一段缓冲区:通过指针把缓冲区分为几个部分:

        已发送并且收到应答的数据、已发送未收到应答的数据、未发送但在对方处理能力内的数据;未发送但不在对方处理能力内的数据;

慢慢滑动,已发送并且收到的数据滑出。

二、 TCP粘包问题【高频面试题】

    TCP协议是面向字节流的协议,接收方不知道消息的界限,不知道一次提取多少数据,这就造成了粘包问题。

1. 粘包问题出现的原因: 

(1)发送端:需要等缓冲区满时才发送出去,造成粘包;发送数据太快

(2)接收端:不及时的接收缓冲区内的包,造成多个包接收。处理数据太慢导致数据在缓冲区缓存

2.避免粘包问题的方法:

(1)对于定长的包,保证每次都按固定大小发送和读取即可;//  结构体

        1)问题:

        结构体对齐问题:假设发送方和接收方分别32字节、64字节;在不同字节平台结构体对齐长度不一样;所以要确保双方结构体对齐方式一样;或者指定按照1个字节对齐,注意,结构体不可放指针;
在双方通信时,发送方的发送数据类型不一样,接收很难确认和区分接受的大小;所以不适用于数据类型多样化;
(2) 对于变长的包,还可以在包和包之间使用明确的分隔符,这个分隔符是由程序员自己来定的,只要保证分隔符不和正文冲突即可。应用层根据分隔符进行解析

(3)自定义一个应用层的数据协议帧;

        如果数据里面有帧头或者帧尾 ====》在帧头后面加入一个长度,这个长度规定,向后多少个

        首先找帧头和有效字节长度,向后读有效字节长度并且读完了看最后是不是帧尾

        在后面加个校验

        所以包含:帧头(AA)、帧尾(BB)、有效数据长度(len)、校验(例如8位和校验()、16位和校验、CRC校验、和其他复杂校验算法)


三、TCP和UDP区别

        都是网络中传输层的传输协议

        UDP叫做,无需建立链接、直接发送给接收方,需要对方的地址,面向数据包;存在丢包,尽最大努力叫覅,不安全不可靠;由于没有很多机制,头部小,资源开销打;要求实时性、不要求数据;

        TCP需要建立TXP链接,面向字节流,有一系列机制可以确保安全机制,三次握手四次挥手、应答机制、流量控制、流动窗口、超时重传;由于很多机制。头部大。资源开销打,要求数据传输安全性高

四、代码练习

        (1)使用TCP实现全双工(进程)

客户端

#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include<unistd.h>
#include <string.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#include <sys/wait.h>
#include<pthread.h>
#include <errno.h>
int main()
{int sockfd = socket(AF_INET, SOCK_STREAM, 0);struct sockaddr_in seraddr;seraddr.sin_family = AF_INET;seraddr.sin_port = htons(50001);seraddr.sin_addr.s_addr = inet_addr("192.168.245.128");char buf[1024] = {0};int ret = connect(sockfd, (struct sockaddr *)&seraddr, sizeof(seraddr));if(ret < 0){perror("connect fail");return -1;}pid_t pid = fork();if(pid < 0){perror("fork fail");return -1;}if(pid > 0){while(1){memset(buf, 0, sizeof(buf));fgets(buf, sizeof(buf), stdin);ssize_t size = send(sockfd, buf, strlen(buf)-1, 0);if(size < 0){perror("send fail");return -1;}}}if(pid == 0){while(1){size_t size = recv(sockfd, buf, sizeof(buf), 0);if(size < 0 ){perror("recv fail");return -1;}if(size == 0){break;}buf[strlen(buf)] = '\0';printf("ser buf = %s\n",buf);}}close(sockfd);
}

服务端

#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include<unistd.h>
#include <string.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#include <sys/wait.h>
#include<pthread.h>
#include <errno.h>
int main()
{int sockfd = socket(AF_INET, SOCK_STREAM, 0);struct sockaddr_in seraddr;seraddr.sin_family = AF_INET;seraddr.sin_port = htons(50001);seraddr.sin_addr.s_addr = inet_addr("192.168.245.128");char buf[1024] = {0};int ret = bind(sockfd, (struct sockaddr *)&seraddr, sizeof(seraddr));if(ret < 0){perror("bind fail");return -1;}ret = listen(sockfd, 10);if(ret < 0){perror("listen fail");return -1;}int connfd = accept(sockfd, NULL, NULL);if(connfd < 0){perror("connfd fail");return -1;}pid_t pid = fork();if(pid < 0){perror("fork fail");return -1;}if(pid > 0){while(1){ssize_t size = recv(connfd, buf, sizeof(buf), 0);if(size < 0){perror("size fail");return -1;}if(size == 0){break;}buf[strlen(buf)] = '\0';printf("buf = %s\n",buf);}}if(pid == 0){while(1){memset(buf, 0, sizeof(buf));fgets(buf, sizeof(buf), stdin);size_t size = send(connfd, buf, strlen(buf)-1, 0);if(size < 0){perror("send fail");return -1;}}}close(connfd);return 0;
}

        (2)使用TCP实现文件传输(传输过来的文件名不变)

客户端

#include <fcntl.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include<unistd.h>
#include <string.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#include <sys/wait.h>
#include<pthread.h>
#include <errno.h>
int main()
{int sockfd = socket(AF_INET, SOCK_STREAM, 0);struct sockaddr_in seraddr;seraddr.sin_family = AF_INET;seraddr.sin_port = htons(50025);seraddr.sin_addr.s_addr = inet_addr("192.168.1.193");char buf[1024] = {0};char buffer[1024] = {0};int ret = connect(sockfd, (struct sockaddr *)&seraddr, sizeof(seraddr));if(ret < 0){perror("connect fail");return -1;}int fd = open("../1.txt", O_RDWR);int fp = open("2.txt", O_RDWR);if(fd < 0){perror("open fail");return -1;}if(fp < 0){perror("open fail");return -1;}pid_t pid = fork();if(pid < 0){perror("fork fail");return -1;}if(pid > 0){while(1){memset(buf, 0, sizeof(buf));memset(buffer, 0, sizeof(buffer));fgets(buf, sizeof(buf), stdin);if(strncmp(buf, "1.txt", 5) == 0){int ret1 =read(fd, buffer, sizeof(buffer));printf("ret1 = %d\n",ret1);// ssize_t size = send(sockfd, buffer, strlen(buffer)-1, 0);ssize_t size = send(sockfd, buffer, ret1, 0);if(size < 0){perror("send fail");return -1;}memset(buffer, 0, sizeof(buffer));}}}if(pid == 0){while(1){memset(buffer, 0, sizeof(buffer));size_t size = recv(sockfd, buffer, sizeof(buffer), 0);if(size < 0 ){perror("recv fail");return -1;}buffer[strlen(buffer)] = '\0';write(fp, buffer,strlen(buffer));//buf[strlen(buf)] = '\0';printf("ser buffer = %s\n",buffer);memset(buffer, 0, sizeof(buffer));}}close(sockfd);
}

服务端

#include <fcntl.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include<unistd.h>
#include <string.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#include <sys/wait.h>
#include<pthread.h>
#include <errno.h>
int main()
{int sockfd = socket(AF_INET, SOCK_STREAM, 0);struct sockaddr_in seraddr;seraddr.sin_family = AF_INET;seraddr.sin_port = htons(50025);seraddr.sin_addr.s_addr = inet_addr("192.168.1.193");char buf[1024] = {0};char buffer[1024] = {0};int ret = bind(sockfd, (struct sockaddr *)&seraddr, sizeof(seraddr));if(ret < 0){perror("bind fail");return -1;}ret = listen(sockfd, 10);if(ret < 0){perror("listen fail");return -1;}int connfd = accept(sockfd, NULL, NULL);if(connfd < 0){perror("connfd fail");return -1;}int fd = open("1.txt", O_RDWR);int fp = open("../2.txt", O_RDWR);pid_t pid = fork();if(pid < 0){perror("fork fail");return -1;}if(pid > 0){while(1){memset(buffer, 0, sizeof(buffer));ssize_t size = recv(connfd, buffer, sizeof(buffer), 0);if(size < 0){perror("size fail");return -1;}buffer[strlen(buffer)] = '\0';write(fd, buffer,strlen(buffer));//buf[strlen(buf)] = '\0';printf("buffer = %s\n",buffer);memset(buffer, 0, sizeof(buffer));}}if(pid == 0){while(1){memset(buffer, 0, sizeof(buffer));memset(buf, 0, sizeof(buf));fgets(buf, sizeof(buf), stdin);if(strncmp(buf, "2.txt", 5) == 0){int ret1 =read(fp, buffer, sizeof(buffer));printf("ret1 = %d\n",ret1);size_t size = send(connfd, buffer, strlen(buffer)-1, 0);if(size < 0){perror("send fail");return -1;}memset(buffer, 0, sizeof(buffer));}}}close(connfd);return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/94098.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/94098.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

alicloud 阿里云有哪些日志 审计日志

1: 阿里有哪些audit log: Audit Related Logs Below table describe the logs available in Log Service that might be applicable to the Security Operations Team. 2: 怎么来分析呢? Overview Its recommended to built a program with SLS Consumer Group which real…

如何理解AP服务发现协议中“如果某项服务需要被配置为可通过多个不同的网络接口进行访问,则应为每个网络接口使用一个独立的客户端服务实例”?

上一句&#xff1a;[PRS_SOMEIPSD_00238]◎ 「如果某项服务需要在多个网络接口上提供&#xff0c;则应为每个网络接口使用一个独立的服务器服务实例。」(RS_SOMEIPSD_00003) 本句&#xff1a;[PRS_SOMEIPSD_00239] 「如果某项服务需要被配置为可通过多个不同的网络接口进行访问…

piecewise jerk算法介绍

piecewise jerk算法介绍 piecewise jerk算法是百度Apollo中的一种用于路径和速度平滑的算法&#xff0c;该算法假设相邻点之间的jerk为常数&#xff0c;基于该假设将平滑问题构建为二次规划问题&#xff0c;调用osqp求解器求解。参考论文为&#xff1a;Optimal Vehicle Path Pl…

分布式蜜罐系统的部署安装

前阵子勒索病毒泛滥&#xff0c;中小企业由于缺少专业EDR&#xff0c;态势感知&#xff0c;IPS等设备&#xff0c;往往是在勒索事件发生之后才后知后觉&#xff0c;也因为缺乏有效的备份策略&#xff0c;导致数据&#xff0c;经济&#xff0c;商业信誉的丧失&#xff0c;甚至还…

定时器互补PWM输出和死区

定时器互补PWM输出和死区互补PWM&#xff08;Complementary PWM&#xff09;H桥、全桥、半桥中的应用为什么需要死区时间互补PWM&#xff08;Complementary PWM&#xff09; 是一种特殊的 PWM 输出模式&#xff0c;通常用于H桥、全桥或半桥电路的驱动。其核心原理是利用定时器…

嵌入式ARM程序高级调试基础:8.QEMU ARM虚拟机与tftp配置

嵌入式ARM程序高级调试基础:8.QEMU ARM虚拟机与tftp配置 文章目录 嵌入式ARM程序高级调试基础:8.QEMU ARM虚拟机与tftp配置 一.总的网络配置过程 二.主机配置 三.QEMU ARM 网络配置 四.主机与虚拟器之间的网络测试 五.TFTP网络配置 5.1 ubuntu主机安装tftp服务器 5.2 设置tft…

【贪心算法】贪心算法六

贪心算法六 1.坏了的计算器 2.合并区间 3.无重叠区间 4.用最少数量的箭引爆气球 点赞👍👍收藏🌟🌟关注💖💖 你的支持是对我最大的鼓励,我们一起努力吧!😃😃 1.坏了的计算器 题目链接: 991. 坏了的计算器 题目分析: 算法原理: 解法一:正向推导 以3转化…

直播预约 | CATIA MODSIM SmartCAE带练营第3期:让每轮设计迭代都快人一步!

▼▼免费报名链接▼▼ 达索系统企业数字化转型在线研讨会https://3ds.tbh5.com/EventDetail.aspx?eid1195&frpt 迅筑官网 ​​

OSI参考模型TCP/IP模型 二三事

计算机网络的学习离不开OSI参考模型&TCP/IP模型对各层功能与任务的了解就是学习的主要内容其二者的区别也是我们应该了解的其中 拥塞控制和流量控制 就是各层功能中 两个易混淆的概念流量控制&#xff08;Flow Control&#xff09;&#xff1a;解决的是发送方和接收方之间速…

DataStream实现WordCount

目录读取文本数据读取端口数据事实上Flink本身是流批统一的处理架构&#xff0c;批量的数据集本质上也是流&#xff0c;没有必要用两套不同的API来实现。所以从Flink 1.12开始&#xff0c;官方推荐的做法是直接使用DataStream API&#xff0c;在提交任务时通过将执行模式设为BA…

imx6ull-驱动开发篇37——Linux MISC 驱动实验

目录 MISC 设备驱动 miscdevice结构体 misc_register 函数 misc_deregister 函数 实验程序编写 修改设备树 驱动程序编写 miscbeep.c miscbeepApp.c Makefile 文件 运行测试 MISC 驱动也叫做杂项驱动&#xff0c;也就是当某些外设无法进行分类的时候就可以使用 MISC…

C# 项目“交互式展厅管理客户端“针对的是“.NETFramework,Version=v4.8”,但此计算机上没有安装它。

C# 项目“交互式展厅管理客户端"针对的是".NETFramework,Versionv4.8”&#xff0c;但此计算机上没有安装它。 解决方法&#xff1a; C# 项目“交互式展厅管理客户端"针对的是".NETFramework,Versionv4.8”&#xff0c;但此计算机上没有安装它。 下载地址…

FFmpeg及 RTSP、RTMP

FFmpeg 是一个功能强大的跨平台开源音视频处理工具集 &#xff0c;集录制、转码、编解码、流媒体传输等功能于一体&#xff0c;被广泛应用于音视频处理、直播、点播等场景。它支持几乎所有主流的音视频格式和协议&#xff0c;是许多媒体软件&#xff08;如 VLC、YouTube、抖音等…

金山办公的服务端开发工程师-25届春招笔试编程题

1.作弊 溪染&#xff1a;六王毕&#xff0c;四海一&#xff1b;蜀山兀&#xff0c;阿房出。覆压三百余里&#xff0c;隔离天日。骊山北构而西折&#xff0c;直走咸阳。二川溶溶&#xff0c;流入宫墙。五步一楼&#xff0c;十步一阁&#xff1b;廊腰缦回&#xff0c;檐牙高啄&am…

注意力机制中为什么q与k^T相乘是注意力分数

要理解 “qkT\mathbf{q} \times \mathbf{k}^TqkT 是注意力分数”&#xff0c;核心是抓住注意力机制的本质目标 ——量化 “查询&#xff08;q&#xff09;” 与 “键&#xff08;k&#xff09;” 之间的关联程度&#xff0c;而向量点积&#xff08;矩阵相乘的元素本质&#xff…

Krea Video:Krea AI推出的AI视频生成工具

本文转载自&#xff1a;Krea Video&#xff1a;Krea AI推出的AI视频生成工具 - Hello123工具导航 ** 一、平台定位与技术特性 Krea Video 是 Krea AI 推出的 AI 视频生成工具&#xff0c;通过结合关键帧图像与文本提示实现精准视频控制。用户可自定义视频首尾帧、为每张图片设…

C++初阶(2)C++入门基础1

C是在C的基础之上&#xff0c;容纳进去了面向对象编程思想&#xff0c;并增加了许多有用的库&#xff0c;以及编程范式 等。熟悉C语言之后&#xff0c;对C学习有一定的帮助。 本章节主要目标&#xff1a; 补充C语言语法的不足&#xff0c;以及C是如何对C语言设计不合理的地方…

ANSI终端色彩控制知识散播(II):封装的层次(Python)——不同的逻辑“一样”的预期

基础高阶各有色&#xff0c;本原纯真动乾坤。 笔记模板由python脚本于2025-08-22 18:05:28创建&#xff0c;本篇笔记适合喜欢终端色彩ansi编码和python的coder翻阅。 学习的细节是欢悦的历程 博客的核心价值&#xff1a;在于输出思考与经验&#xff0c;而不仅仅是知识的简单复述…

前端无感刷新 Token 的 Axios 封装方案

在现代前端应用中&#xff0c;基于 Token 的身份验证已成为主流方案。然而&#xff0c;Token 过期问题常常困扰开发者 —— 如何在不打断用户操作的情况下自动刷新 Token&#xff0c;实现 "无感刷新" 体验&#xff1f;本文将详细介绍基于 Axios 的解决方案。什么是无…

【数据结构】线性表——链表

这里写自定义目录标题线性表链表&#xff08;链式存储&#xff09;单链表的定义单链表初始化不带头结点的单链表初始化带头结点的单链表初始化单链表的插入按位序插入带头结点不带头结点指定结点的后插操作指定结点的前插操作单链表的删除按位序删除&#xff08;带头结点&#…