当前位置: 首页 > news >正文

TCP:传输控制协议

1:TCP特点:

(1)面向数据流:
(2)有连接(通信之前必须建立连接)
(3)安全可靠的传输机制
(4)机制复杂,网络资源开销大,
(5)本质只能实现一对一的通信(使用TCP的并发方式可以实现一对多通信)

2:TCP确保安全可靠的机制:

三次握手和四次挥手机制:

三次握手:发生在TCP建立连接时,需要进行三次握手操作,为了确保收发双方在通信之前都已准备数据

SYN:客户端请求和服务端建立连接
ACK:响应报文标志位

三次握手:
在这里插入图片描述

TCP四次挥手:TCP断开连接时,需要进行四次挥手,确保断开连接前双方都已通信结束:先发送FIN的一端数据已经发送完了,为防止另一端还在发送数据(数据还没发送完),另一端发送的ACK和FIN不能同时发送,在另一端完全发送完后再发送FIN

FIN:请求断开连接标志位

ACK:响应报文标志位

在这里插入图片描述

TCP编程流程:

在这里插入图片描述
在这里插入图片描述在这里插入图片描述

三次握手阶段:

在这里插入图片描述

四次挥手阶段:

服务端close()-》客户端send()的过程
在这里插入图片描述
在这里插入图片描述在这里插入图片描述

代码:

#include<stdio.h>
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h> /* superset of previous */
#include <sys/types.h>          /* See NOTES */
#include <arpa/inet.h>
#include <unistd.h>
#include<string.h>
int main(void)
{int sockfd=socket(AF_INET,SOCK_STREAM,0);if(sockfd<0){perror("socket error\n");return -1;}struct sockaddr_in seraddr;seraddr.sin_family=AF_INET;seraddr.sin_port=htons(50000);seraddr.sin_addr.s_addr=inet_addr("192.168.0.120");int ret = connect(sockfd,(struct sockaddr *)&seraddr,sizeof(seraddr));if(ret <0){perror("connect error\n");return -1;}ssize_t cnt =send(sockfd,"hello world",11,0);if(cnt<0){perror("send error\n");return -1;}printf("cnt = %ld\n",cnt);close(sockfd);return 0;
}

服务端函数:

listen函数:

在这里插入图片描述

accept函数:

在这里插入图片描述

recv函数:接收通讯套接字-

在这里插入图片描述
对方断开链接时,将会返回0。

代码

#include<stdio.h>
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h> /* superset of previous */
#include <sys/types.h>          /* See NOTES */
#include <arpa/inet.h>
#include <unistd.h>
#include<string.h>int main(int argc, const char *argv[])
{//socket()//bind()//listen()//accept()//recv()//send()//close()int sockfd = socket(AF_INET, SOCK_STREAM, 0);if (sockfd < 0){perror("socket error");return -1;}struct sockaddr_in seraddr;seraddr.sin_family = AF_INET;seraddr.sin_port = htons(50000);seraddr.sin_addr.s_addr = inet_addr("192.168.0.179");int ret = bind(sockfd, (struct sockaddr *)&seraddr, sizeof(seraddr));if (ret < 0){perror("bind error");return -1;}ret = listen(sockfd, 10);if (ret < 0){perror("listen error");return -1;}int connfd = accept(sockfd, NULL, NULL);if (connfd < 0){perror("accept error");return -1;}char buff[1024] = {0};ssize_t cnt = recv(connfd, buff, sizeof(buff), 0);if (cnt < 0){printf("recv error");return -1;}printf("cnt = %ld, buff = %s\n", cnt, buff);close(connfd);close(sockfd);return 0;
}

TCP粘包问题:

发送方应用层发送的多包数据将来在接收方可能一次读到,产生了粘连。

1:发送方将应用层的两包数据整合为一包发送。

2:接收方不知道一包数据的字节数,多包数据在接收方缓冲区缓存,在接收时将多包数据一起接收了

在这里插入图片描述

解决粘包问题的方法:

1:减慢发送方的发送速度,在每次发送后给它延迟1u秒,usleep(1)。

2:发送方发送指定大小,接收方接收指定大小

指定大小:发送结构体

注意:跨平台间数据传输时要注意结构体对齐问题。

在这里插入图片描述
32位平台和64位平台的结构体大小不同。
在这里插入图片描述
在这里插入图片描述

3:应用层为发送的数据增加分隔符,利用分隔符解析

在这里插入图片描述

4:封装数据帧格式进行发送(提前自定义协议)

在这里插入图片描述

还要封装帧头和帧尾

在这里插入图片描述
AA到BB之间的数据为完整的一帧数据,为防止之间出现帧头或帧尾:
在这里插入图片描述
帧头后封装长度
在这里插入图片描述

帧头

帧尾

有效数据长度:C0

有效数据:

在这里插入图片描述
校验:
在这里插入图片描述

http://www.dtcms.com/a/347282.html

相关文章:

  • JAVA核心基础篇-递归
  • C 语言标准输入输出头文件stdio.h及其常见用法
  • 【读论文】Qwen-Image技术报告解读
  • 云原生高级——K8S总概
  • ArkTS 语言全方位解析:鸿蒙生态开发新选择
  • 双指针:成最多水的容器
  • 使用 eventpp 构建跨 RT-Thread 与 ARM-Linux 的轻量级 Active Object(AO)事件驱动框架
  • AI Agent系列(十三) -智能体架构的真相
  • LoRA 微调
  • 探索 JUC:Java 并发编程的神奇世界
  • 单调栈详解
  • Vue环境组件node.js安装
  • C语言---数据类型
  • Qt中使用MySQL数据库
  • git实战(8)git高阶命令分析【结合使用场景】
  • ADC系统中的信噪比(SNR)
  • 容器安全实践(二):实践篇 - 从 `Dockerfile` 到 Pod 的权限深耕
  • 多模态医学图像融合:解锁顶会顶刊中的医学影像新视界
  • 【GaussDB】使用MySQL客户端连接到GaussDB的M-Compatibility数据库
  • 智慧零售漏扫率↓79%!陌讯多模态融合算法在智能收银与货架管理的实战解析
  • 【Linux】深度学习Linux下的包管理器yum/apt
  • Day22: Python涡轮增压计划:用C扩展榨干最后一丝性能!
  • 微前端架构常见框架
  • 深度学习之PyTorch框架(安装,手写数字识别)
  • pid自适应调节实战设计-基于输出电流的PI参数切换方案
  • deepseek应用技巧-MCP服务操作网页和文档
  • ESP32应用——UDP组播/广播(ESP-IDF框架)
  • AI 辅助编程完全新手指南 - 从零基础到高效协作
  • Java试题-选择题(15)
  • flink常见问题之超出文件描述符限制