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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈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;接下来跟随作者一起来学习吧…