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

网络:tcp

服务器//客户端模型(常见模型分析)

1.c//s        服务器·(c)专用        HTTP协议,自定义协议,标准协议。      资源大部分在cli客户端

不受协议影响,较复杂。

2.b//s        服务器(c)通用        HTTP协议。             资源大部分服务器发送至客户端(ser->cli)

受到HTTP协议影响,功能较简单。

3.p2p        在线直播,文件下载。

TCP:传输控制协议。

流式套接字:数据和数据之间连续;先发先收;数据连续;可靠传输。

TCP传输,当链路搭建后,会维持通道。建立连接过程包含“三次握手,四次挥手”。全双工通信。

TCP传输可靠原因:应答,超时重传。(只要发送就会返回应答。已发送未应答,数据会重发,等待应答信号。)

“三次握手,四次挥手”流程图

SYN:建立连接;FIN:释放连接。

TCP三次握手 (Three-way Handshake)

目的: 建立一条TCP连接。
过程:

  1. 第一次握手 (SYN): 客户端先向服务器发送一个SYN包(SYN=1),并随机生成一个序列号(seq=x),进入SYN_SENT状态。

  2. 第二次握手 (SYN+ACK): 服务器收到SYN包后,必须确认客户端的SYN。同时自己也发送一个SYN包(SYN=1)。因此会发送一个SYN-ACK包(SYN=1, ACK=1),并确认号ack=x+1,同时自己也随机生成一个序列号seq=y,进入SYN_RCVD状态。

  3. 第三次握手 (ACK): 客户端收到服务器的SYN-ACK包后,向服务器发送一个确认包ACK(ACK=1),确认号ack=y+1,序列号seq=x+1。完成后,客户端和服务器都进入ESTABLISHED状态,连接建立成功。


TCP四次挥手 (Four-way Wavehand)

目的: 终止一条TCP连接。
过程:

  1. 第一次挥手 (FIN): 主动关闭方(可以是客户端或服务器)发送一个FIN包(FIN=1),并指定一个序列号(seq=u),进入FIN_WAIT_1状态。

  2. 第二次挥手 (ACK): 被动关闭方收到FIN包后,发送一个ACK包(ACK=1)作为确认,确认号为ack=u+1,并带上自己的序列号seq=v。此时被动关闭方进入CLOSE_WAIT状态,主动关闭方收到这个ACK后进入FIN_WAIT_2状态。

  3. 第三次挥手 (FIN): 被动关闭方处理完所有数据后,也发送一个FIN包(FIN=1),并指定一个序列号(seq=w),进入LAST_ACK状态。

  4. 第四次挥手 (ACK): 主动关闭方收到FIN后,发送一个ACK包(ACK=1)作为确认,确认号为ack=w+1,序列号为seq=u+1。然后进入TIME_WAIT状态,等待一段时间(2MSL)后彻底关闭。被动关闭方收到这个ACK后,立即关闭连接。

TCP协议->流程(函数)

服务器端:tcp ser->(建立)socket->(绑定)bind->(监听)listen->(通信)accept->(接收)recv->(发送)send

客户端:tcp cli->(建立)socket->(主动发起连接->三次握手)connect->(发送)send->(接收)recv

TCP/UDP,缓冲区64k。TCP缓冲区是双缓冲区。收发都是64k,不干扰。UDP是单个缓冲区64k。

数据的粘包(发送方发送数据,接收方无法解析数据。)解决办法:

1.设置边界。

2.固定大小。

3.自定义协议。

具体例子:代码能运行成功,就是图片加载不出来。

服务端:

typedef struct sockaddr*(SA);
int	main(int argc, char **argv)
{//监听套接字int listfd=socket(AF_INET,SOCK_STREAM,0);if (-1==listfd){perror("listfd err...");return 1;}//man 7 ipstruct sockaddr_in ser,cli;//清空bzero(&ser,sizeof(ser));bzero(&cli, sizeof(cli));ser.sin_family=AF_INET;ser.sin_port =htons(50000);//INADDR_ANY代表网卡信息ser.sin_addr.s_addr=INADDR_ANY;int ret= bind(listfd,(SA)&ser,sizeof(ser));if (-1==ret){perror("ret err...");return 1;}//listen中3的原因——服务器三次握手的排队数,不是连接客户端个数。listen(listfd, 3);socklen_t len = sizeof(cli);//通信套接字int conn = accept(listfd, (SA)&cli, &len);if(-1==conn){perror("conn err...");return 1;}int fd = open("2.png",O_WRONLY|O_CREAT|O_TRUNC,0666);if (-1==fd){perror("fd err...");return 1;}time_t tm;while (1){char buf[1024]={0};int ret= recv(conn, buf, sizeof(buf), 0);if (ret<=0){break;}time(&tm);write(fd, buf, ret);}close(listfd);close(conn);close(fd);//system("pause");return 0;
}

客户端:

typedef struct sockaddr*(SA);
int	main(int argc, char **argv)
{//监听套接字int conn=socket(AF_INET,SOCK_STREAM,0);if (-1==conn){perror("conn err...");return 1;}//man 7 ipstruct sockaddr_in ser;//清空bzero(&ser,sizeof(ser));ser.sin_family=AF_INET;ser.sin_port =htons(50000);//INADDR_ANY代表网卡信息ser.sin_addr.s_addr=INADDR_ANY;int ret= connect(conn,(SA)&ser,sizeof(ser));if (-1==ret){perror("ret err...");return 1;}int fd = open("test.png", O_RDONLY);if (-1 == fd){perror("open error\n");return 1;}while (1){char buf[1024]={0};bzero(buf, sizeof(buf));int ret = read(fd, buf, sizeof(buf));if (ret <= 0){break;}send(conn, buf, ret, 0);bzero(buf, sizeof(buf));recv(conn, buf, sizeof(buf), 0);// printf("ser:%s\n",buf); }close(conn);close(fd);//system("pause");return 0;
}

解决方案

1. 使用协议头

c

复制下载

// 发送文件前先发送文件信息
struct file_info {uint32_t file_size;uint32_t file_name_len;// 后续跟文件名和数据
};

2. 使用固定长度的结束标记

c

复制下载

// 使用独特的结束标记,如8字节的特殊序列
const char END_MARKER[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xAA, 0x55, 0xCC};

3. 使用文件大小作为传输结束条件

c

复制下载

// 客户端先发送文件大小
uint32_t file_size = get_file_size("test.png");
send(conn, &file_size, sizeof(file_size), 0);// 服务器端根据文件大小接收
uint32_t total_received = 0;
while (total_received < file_size)
{int ret = recv(conn, buf, sizeof(buf), 0);write(fd, buf, ret);total_received += ret;
}

文章转载自:

http://1tkdOkWV.rwLnk.cn
http://R136Lmj3.rwLnk.cn
http://FyuB6wUk.rwLnk.cn
http://WwsLYhaW.rwLnk.cn
http://j1yAoEAD.rwLnk.cn
http://hR6HSPOd.rwLnk.cn
http://tHZ5dmcO.rwLnk.cn
http://hOoVxYyR.rwLnk.cn
http://pCgNe0pZ.rwLnk.cn
http://gRysg8uJ.rwLnk.cn
http://wjqX84vA.rwLnk.cn
http://IpBWxT8l.rwLnk.cn
http://jqwwggWP.rwLnk.cn
http://BpivgK6I.rwLnk.cn
http://SaCFRc5G.rwLnk.cn
http://6xg4KoZ0.rwLnk.cn
http://Pi6ljylY.rwLnk.cn
http://q6hYqsQc.rwLnk.cn
http://iphyxQJt.rwLnk.cn
http://YR4d5Jqj.rwLnk.cn
http://YAr7vt1H.rwLnk.cn
http://kM7oHYYD.rwLnk.cn
http://1hPPoQNl.rwLnk.cn
http://mjrFnMKG.rwLnk.cn
http://FJwAgPUD.rwLnk.cn
http://3KJ49eEu.rwLnk.cn
http://pXoI48Cn.rwLnk.cn
http://VQUbtCRc.rwLnk.cn
http://AorY17S3.rwLnk.cn
http://cI9ngW8w.rwLnk.cn
http://www.dtcms.com/a/364468.html

相关文章:

  • JavaScript闭包、原型链、事件循环,一文彻底讲明白(小白也能懂)
  • 学习笔记:MYSQL(3)(常用函数和约束)
  • dvs dvfs avs avfs 低功耗技术的区别
  • DBSCAN 密度聚类分析算法
  • 第二章:技术基石:写出“活”的代码(2)
  • DVWA靶场通关笔记-存储型XSS(Stored Impossible级别)
  • K8s Pod CrashLoopBackOff:从镜像构建到探针配置的排查过程
  • AI Agent重构SOC:下一代智能安全运营平台的能力跃迁
  • 解析SWOT分析和PV/UV这两个在产品与运营领域至关重要的知识点。
  • 【LeetCode 热题 100】72. 编辑距离——(解法一)记忆化搜索
  • 【LM358AD差分检测电压差】2022-11-30
  • 刻意练习理论
  • C++ 多线程编程
  • 【IO】进程间通信(IPC)练习
  • CAD/BIM软件产品技术深度分析文章写作计划
  • 7.4Element Plus 分页与表格组件
  • java spring cloud 企业工程管理系统源码+二次开发+定制化服务
  • 深兰科技AI问诊助手走访打浦桥街道社区卫生服务中心
  • Llama.cpp与CUDA Graph:深度学习推理框架的兼容性深度解析
  • Elasticsearch(text和keyword)区别分析
  • 怎么删除word空白页?【图文详解】删除最后一页空白页?5种删除word文档空白页方法?
  • Few-Shot Prompting 实战:用5个例子让GPT-4学会复杂任务
  • 线程与同步
  • 【Unity Shader学习笔记】(四)Shader编程
  • Java设计模式之结构型—适配器模式
  • SQLAlchemy ORM 入门教程
  • Low-Light Image Enhancement via Structure Modeling and Guidance 论文阅读
  • SQLint3 模块如何使用
  • Linux awk命令完全指南:从原理到实战,搞定文本处理难题
  • SQL(window)日志在linux 下查看