Linux24 -- tcp相关概念、多个客户端链接服务端代码
创始人
2024-05-29 06:33:44
0

一、tcp相关概念

tcp协议特点:面向连接的、可靠的、流式服务

建立链接:三次握手,发送 SYN
断开链接;四次挥手,发送 FIN

tcp、udp都同属于传输层,在网络层使用ip协议,都要将数据交给IP协议,但ip协议是无连接、不可靠的
在这里插入图片描述

tcp的可靠性:

应答确认
超时重传
乱序重排(先发出去的报文不一定先到,路劲可能不一样)
去重(发送确认信息可能丢失导致报文多发)
滑动窗口,进行流量控制(收发信息时,程序处理能力有限,缓存区的大小有限,当发送过快超出接收能力范围时,会对齐进行控制,通过滑动窗口进行流量控制)
流式服务(连续多次的send,可能recv的情况不一样,可能多收也可能只收一部分,不是一一对应的)
粘包:两次发送的数据可能背一次收到,多个数据包被连续存储于连续的缓存中,在对数据包进行读取时由于无法确定发生方的发送边界,而采用某一估测值大小来进行数据读出,若双方的size不一致时就会使指发送方发送的若干包数据到接收方接收时粘成一包,从接收缓冲区看,后一包数据的头紧接着前一包数据的尾。

多个客户端链接服务端代码

同时运行两个客户端进行链接

在这里插入图片描述

结束其中一个客户端,一个客户端进行链接

在这里插入图片描述

结束两个客户端,无客户端进行连接

在这里插入图片描述

将服务器端关闭

在这里插入图片描述

代码:

1、

#include 
#include 
#include 
#include #include 
#include 
#include #include int socket_init();void recv_data(int c)
{while( 1 ){char buff[128] = {0};int n = recv(c,buff,127,0);//0代表if( n <= 0)//<代表失败,==代表客户端关闭{break;}printf("buff = %s\n",buff);send(c,"ok",2,0);}close(c);
}void wait_child(int sig)
{wait(NULL);
}int main()
{signal(SIGCHLD,wait_child);//创建套接字int sockfd = socket_init();if( sockfd == -1){exit(0);}while( 1 ){//定义表示套接字地址的变量struct sockaddr_in caddr;int len = sizeof(caddr);int c = accept(sockfd,(struct sockaddr* )&caddr,&len);//会有阻塞if( c < 0){continue;}pid_t pid = fork();if( pid == -1){close(c);continue;}if(pid == 0)//判断是否在子进程,为1为子进程{//接收客户端数据recv_data(c);exit(0);}close(c);//wait(NULL);//能解决将死进程,但影响应用要求}
}int socket_init()
{//创建一个在传输层使用tcp协议的一个套接字int sockfd = socket(AF_INET,SOCK_STREAM,0); //AF_INET --地址zhu,目前的固定的、服务类型 ---- tcp流式服务if(sockfd == -1)//创建失败{return -1;}//定义一个套接字地址,一个ipv4 专用的地址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");//将字符串转成无符号整形//指定ip端口int res = bind(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));if( res == -1){printf("bind err\n");return -1;}//创建监听队列res = listen(sockfd,5);if( res == -1){return -1;}return sockfd;}

2、signal(SIGCHLD,SIG_IGN);

//明确的忽略信号,相当于告诉系统子进程结束了,直接将其内核中的tcp处理掉,不考虑退出码 在只能在linux上使用,不能在unix上使用

#include 
#include 
#include 
#include #include 
#include 
#include #include int socket_init();void recv_data(int c)
{while( 1 ){char buff[128] = {0};int n = recv(c,buff,127,0);//0代表if( n <= 0)//<代表失败,==代表客户端关闭{break;}printf("buff = %s\n",buff);send(c,"ok",2,0);}close(c);
}void wait_child(int sig)
{wait(NULL);
}int main()
{//signal(SIGCHLD,wait_child);signal(SIGCHLD,SIG_IGN); //明确的忽略信号,相当于告诉系统子进程结束了,直接将其内核中的tcp处理掉,不考虑退出码    在只能在linux上使用,不能在unix上使用//创建套接字int sockfd = socket_init();if( sockfd == -1){exit(0);}while( 1 ){//定义表示套接字地址的变量struct sockaddr_in caddr;int len = sizeof(caddr);int c = accept(sockfd,(struct sockaddr* )&caddr,&len);//会有阻塞if( c < 0){continue;}pid_t pid = fork();if( pid == -1){close(c);continue;}if(pid == 0)//判断是否在子进程,为1为子进程{//接收客户端数据recv_data(c);exit(0);}close(c);//wait(NULL);//能解决将死进程,但影响应用要求}
}int socket_init()
{//创建一个在传输层使用tcp协议的一个套接字int sockfd = socket(AF_INET,SOCK_STREAM,0); //AF_INET --地址zhu,目前的固定的、服务类型 ---- tcp流式服务if(sockfd == -1)//创建失败{return -1;}//定义一个套接字地址,一个ipv4 专用的地址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");//将字符串转成无符号整形//指定ip端口int res = bind(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));if( res == -1){printf("bind err\n");return -1;}//创建监听队列res = listen(sockfd,5);if( res == -1){return -1;}return sockfd;}

相关内容

热门资讯

监控摄像头接入GB28181平... 流程简介将监控摄像头的视频在网站和APP中直播,要解决的几个问题是:1&...
Windows10添加群晖磁盘... 在使用群晖NAS时,我们需要通过本地映射的方式把NAS映射成本地的一块磁盘使用。 通过...
protocol buffer... 目录 目录 什么是protocol buffer 1.protobuf 1.1安装  1.2使用...
在Word、WPS中插入AxM... 引言 我最近需要写一些文章,在排版时发现AxMath插入的公式竟然会导致行间距异常&#...
【PdgCntEditor】解... 一、问题背景 大部分的图书对应的PDF,目录中的页码并非PDF中直接索引的页码...
修复 爱普生 EPSON L4... L4151 L4153 L4156 L4158 L4163 L4165 L4166 L4168 L4...
Fluent中创建监测点 1 概述某些仿真问题,需要创建监测点,用于获取空间定点的数据࿰...
educoder数据结构与算法...                                                   ...
MySQL下载和安装(Wind... 前言:刚换了一台电脑,里面所有东西都需要重新配置,习惯了所...
MFC文件操作  MFC提供了一个文件操作的基类CFile,这个类提供了一个没有缓存的二进制格式的磁盘...