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

qq群网站制作婚礼策划网站建设

qq群网站制作,婚礼策划网站建设,仙桃做网站的公司有哪些,商城网站大概多少钱目录 一、三次握手建立连接 1.1 标记位 1.2 三次握手的过程 二、四次挥手断开连接 三、模拟服务器和客户端收发数据 四、多线程并发处理 五、TCP粘包问题 5.1 什么是TCP粘包? 5.2 TCP粘包会有什么问题? 5.3 TCP粘包的解决方法? 一、三…

目录

一、三次握手建立连接

1.1 标记位

1.2 三次握手的过程

二、四次挥手断开连接

 三、模拟服务器和客户端收发数据

四、多线程并发处理

五、TCP粘包问题

5.1 什么是TCP粘包?

5.2 TCP粘包会有什么问题?

5.3 TCP粘包的解决方法?


一、三次握手建立连接

1.1 标记位

        SYN:用于建立连接的初始握手。发送方发送一个SYN报文段给接收方,请求建立连接。

        ACK:用于确认数据的传输。当成功接收到数据后,接收方发送一个带有ACK标记的报文段回复发送方,确认已经收到了数据。

        FIN:用于关闭连接。当发送方发送完所有数据后,会发送一个带有FIN标记的报文段,请求关闭连接。接收方在收到FIN报文段后,发送一个带有ACK标记的报文段进行确认,并使用一个定时器在一段时间后关闭连接。

1.2 三次握手的过程

三次握手是TCP协议中用于建立连接的过程,具体步骤如下:

  1. 客户端向服务器发送一个SYN(同步)的数据包,表示客户端请求建立连接。该数据包中还包含客户端随机生成的初始序列号(Sequence Number,seq),比如 seq = x。
  2. 服务器收到客户端发送的SYN数据包后,向客户端发送一个ACK(确认)和SYN的组合数据包,服务器将自己的初始序列号(seq = y)发送给客户端,同时将客户端的序列号加 1 作为确认号(Acknowledgment Number,ack = x + 1),表示服务器同意建立连接,并向客户端发送确认信息。
  3. 客户端收到服务器发送的ACK和SYN的数据包后,向服务器发送一个ACK确认数据包,该包的确认号为服务器的序列号加 1(ack = y + 1),而序列号为客户端在第一次握手中发送的序列号加 1(seq = x + 1),表示客户端也同意建立连接。

经过以上三个步骤,客户端和服务器就成功建立了连接,可以开始进行数据传输。这个过程就是TCP协议中三次握手的过程。

图解如下:

二、四次挥手断开连接

四次挥手是TCP协议中用于关闭连接的过程,具体步骤如下:

  1. 第一次挥手:当客户端确定自己已经没有数据要发送时,向服务器发送一个FIN(结束)数据包,其中包含自己的序列号(seq = u),表示客户端关闭数据传输。
  2. 第二次挥手:服务器接收到客户端发送的FIN后,向客户端发送一个ACK确认数据包,确认号为客户端的序列号加 1(ack = u + 1),表示服务器收到了关闭请求。此时,服务器可能还有数据需要继续发送,所以连接不会立即关闭,而是进入半关闭状态。
  3. 第三次挥手:当服务器确定自己没有数据要发送时,向客户端发送一个FIN数据包,其中包含自己的序列号(seq = v),表示服务器也准备关闭连接。
  4. 第四次挥手:客户端接收到服务器发送的FIN后,向服务器发送一个ACK确认数据包,确认号为服务器的序列号加 1(ack = v + 1),序列号为之前发送 FIN 包时的序列号加 1(seq = u + 1),表示客户端收到了关闭请求,连接正式关闭。

通过以上四个步骤,客户端和服务器完成了关闭连接的过程。值得注意的是,四次挥手中的每一次挥手都需要对方发送确认,确保双方都能安全地关闭连接。

图解如下:

那么,挥手能不能是3次呢?答案是可以的,第二次挥手和第三次挥手是可以合并在一起的。

 三、模拟服务器和客户端收发数据

服务器ser

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>int socket_init();int main()
{int sockfd=socket_init();if(sockfd==-1){exit(1);}while(1){struct sockaddr_in caddr;//记录客户端地址ip,portint len=sizeof(caddr);int c=accept(sockfd,(struct sockaddr*)&caddr,&len);//caddr存放客户端ip,port,可能会阻塞if(c<0){continue;}printf("accept c=%d\n",c);while(1){char buff[128]={0};int n=recv(c,buff,127,0);//有可能阻塞,如果返回-1则失败,是0则对方关闭了if(n<=0){break;}printf("recv:%s\n",buff);send(c,"ok",2,0);//write(c,"ok",2);}close(c);printf("cilent close\n");}
}
int socket_init()
{int sockfd=socket(AF_INET,SOCK_STREAM,0);//TCP,创建套接字if(sockfd==-1){return -1;}struct sockaddr_in saddr;//ipv4地址族,对应套接字的地址memset(&saddr,0,sizeof(saddr));saddr.sin_family=AF_INET;saddr.sin_port=htons(6000);saddr.sin_addr.s_addr=inet_addr("127.0.0.1");int res=bind(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));//绑定ip,port,指定if(res==-1){printf("bind err\n");return -1;}res=listen(sockfd,5);//创建监听队列if(res==-1){return -1;}return sockfd;
}
  1. 先调用socket_init()函数初始化服务器端的套接字,绑定IP和端口,并开始监听连接请求。
  2. 不断循环accept()函数接受客户端的连接请求,一旦有客户端连接则创建一个新的套接字来处理与客户端的通信。
  3. 在客户端连接成功后,进入一个无限循环,不断接收客户端发送的消息,并打印消息内容。
  4. 如果接收到的消息长度小于等于0,则说明客户端关闭了连接,跳出循环,关闭与客户端的连接。
  5. 如果收到消息,则回复客户端消息为"ok", 继续接受下一条消息。

客户端cil

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>int main()
{int sockfd=socket(AF_INET,SOCK_STREAM,0);if(sockfd==-1){exit(1);}struct sockaddr_in saddr;//服务器的地址memset(&saddr,0,sizeof(saddr));saddr.sin_family=AF_INET;saddr.sin_port=htons(6000);saddr.sin_addr.s_addr=inet_addr("127.0.0.1");int res=connect(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));//发起连接,三次握手if(res==-1){printf("connet err\n");exit(1);}while(1){printf("input:\n");char buff[128]={0};fgets(buff,128,stdin);if(strncmp(buff,"end",3)==0){break;}send(sockfd,buff,strlen(buff)-1,0);memset(buff,0,128);recv(sockfd,buff,127,0);printf("buff=%s\n",buff);}close(sockfd);exit(0);
}
  1. 创建了一个套接字socket,并指定为AF_INET和SOCK_STREAM,表示使用IPv4和TCP协议。
  2. 初始化服务器的地址saddr,包括IP地址为"127.0.0.1"、端口号为6000等信息。
  3. 调用connect()函数连接到服务器端,进行三次握手建立连接。
  4. 进入一个循环,不断接收用户输入的消息,将消息发送给服务器,并接收服务器的回复。
  5. 如果用户输入为"end",则跳出循环,关闭套接字,结束程序。

运行结果:

那么send后会直接将数据发送出去吗?答案不然,会将数据先发送到发送缓冲区,然后将数据发给接收缓冲区,最后才会接收到数据。

我们来验证一下:

 把ser.c中的int n = recv(c,buff,127,0)改为int n = recv(c,buff,1,0),执行后结果:

每输一个应该输出五个ok,但此时只输出一个ok,剩下四个ok在recv的缓冲区中,4个ok八个字符所以缓冲区有8个字符。

通过netstat -natp 命令可以显示

再输入一个a,输出四个ok

此时缓冲区中有一个ok,2个字符

TCP字节流服务

四、多线程并发处理

服务器ser

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<pthread.h>int socket_init();
void* fun(void* arg)
{int* p=(int*)arg;int c=*p;free(p);while(1){char buff[128]={0};int n=recv(c,buff,127,0);//有可能阻塞,如果返回-1则失败,是0则对方关闭了if(n<=0){break;}printf("recv:%s\n",buff);send(c,"ok",2,0);//write(c,"ok",2);}close(c);printf("cilent close\n");
}
int main()
{int sockfd=socket_init();if(sockfd==-1){exit(1);}while(1){struct sockaddr_in caddr;//记录客户端地址ip,portint len=sizeof(caddr);int c=accept(sockfd,(struct sockaddr*)&caddr,&len);//caddr存放客户端ip,port,可能会阻塞if(c<0){continue;}printf("accept c=%d\n",c);int* p=(int*)malloc(sizeof(int));if(p==NULL){close(c);continue;}*p=c;pthread_t id;pthread_create(&id,NULL,fun,(void*)p);}
}
int socket_init()
{int sockfd=socket(AF_INET,SOCK_STREAM,0);//TCP,创建套接字if(sockfd==-1){return -1;}struct sockaddr_in saddr;//ipv4地址族,对应套接字的地址memset(&saddr,0,sizeof(saddr));saddr.sin_family=AF_INET;saddr.sin_port=htons(6000);saddr.sin_addr.s_addr=inet_addr("127.0.0.1");int res=bind(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));//绑定ip,port,指定if(res==-1){printf("bind err\n");return -1;}res=listen(sockfd,5);//创建监听队列if(res==-1){return -1;}return sockfd;
}

客户端cil

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>int main()
{int sockfd=socket(AF_INET,SOCK_STREAM,0);if(sockfd==-1){exit(1);}struct sockaddr_in saddr;//服务器的地址memset(&saddr,0,sizeof(saddr));saddr.sin_family=AF_INET;saddr.sin_port=htons(6000);saddr.sin_addr.s_addr=inet_addr("127.0.0.1");int res=connect(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));//发起连接,三次握手if(res==-1){printf("connet err\n");exit(1);}while(1){printf("input:\n");char buff[128]={0};fgets(buff,128,stdin);if(strncmp(buff,"end",3)==0){break;}send(sockfd,buff,strlen(buff)-1,0);memset(buff,0,128);recv(sockfd,buff,127,0);printf("buff=%s\n",buff);}close(sockfd);exit(0);
}

 运行结果:

五、TCP粘包问题

5.1 什么是TCP粘包?

        TCP粘包是指发送方连续发送的多个数据包,在传输过程中可能会被TCP协议合并成一个大的数据包,在接收方收到时无法正确区分这些数据包的边界,导致粘在一起,从而引起粘包现象。这样就会影响接收方对数据的解析和处理简而言之,就是多次send发送数据,被对方一次recv收到了。

5.2 TCP粘包会有什么问题?

  1. 数据解析错误:如果接收方无法正确区分数据包的边界,可能导致数据解析错误,无法按照预期的方式处理数据。
  2. 数据错误:如果多个数据包粘在一起,可能导致数据包数据内容混杂,造成数据错误或丢失。
  3. 性能影响:数据粘包会增加解析数据的复杂性,影响系统性能。

5.3 TCP粘包的解决方法?

  1. 消息定长:在发送方和接收方约定固定的消息长度,每次发送和接收的数据长度相同,这样接收方可以根据固定长度来截取数据包。
  2. 使用特殊符号分隔:在数据包之间加入特殊符号作为分隔符,接收方根据分隔符来区分不同数据包。
  3. 增加消息头:在数据包头部添加额外的消息头信息,包括消息长度等,接收方通过消息头信息来解析数据包。
http://www.dtcms.com/wzjs/566875.html

相关文章:

  • .net做网站开发常见的c2c平台有
  • 广东建设继续教育网站首页wordpress知名网站
  • 低价网站制作墨西哥网站后缀
  • 网站制作致谢词做网站的文案怎么写
  • 可以仿做网站吗电商平台网站模板
  • 白云手机网站建设北京广告设计公司排行
  • 百度手机助手app官方下载seo对企业网站运营有何意义
  • 做网站该读啥济南网站建设工作
  • 昆明网站运营高端建筑物图片
  • 寻找南京帮助做网站的单位wordpress仿微信菜单栏
  • 大型网站建设报价企业的网站建设与设计论文
  • 中国美院网站建设公司企业网站开发多少钱
  • 色流网站如何做wordpress安装数据库连接错误
  • 做爰动态视频网站成都网站建设哪儿济南兴田德润怎么联系
  • 怎么创建网站域名wordpress菜单导航栏
  • 会展网站建设成功的原因做翻译网站 知乎
  • wordpress版权兰州seo网站建设
  • seo网站推广技术app软件开发不包括
  • 绍兴住房和城乡建设厅网站12306网站开发商
  • 辽宁手机版建站系统信息成都建设网站价格
  • 网站建设素材模板下载wordpress 3.2.1漏洞
  • 如何开 网站建设公司帝国网站地图插件
  • 专业建站公司前景做五金上哪个网站推广
  • 昆明网站建设价格房屋装修设计公司
  • 基层建设刊物网站深圳哪家网站公司好
  • 深圳手机网站建设公司网站备案 网站建设方案书
  • 网站查询工具seowordpress能做交互类网站
  • 现在用什么cms做网站好论学院网站建设项目的进度管理
  • 网上医疗和医院网站建设制作宁波网站设计方案
  • wordpress不显示评论框东莞seo建站怎么投放