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

网络I/O学习(一)

一、什么是网络IO?

就是客户端和服务端之间的进行通信的通道(fd)。

二、网络IO通信步骤

1、建立套接字

int socketfd = socket(AF_INET, SOCK_STREAM, 0);struct sockaddr_in servaddr;
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY); //绑定0.0.0.0,Linux上有三张网卡,eth0:桥接,eth1:NAT,lo:回环,// 0.0.0.0代表任意一个收到数据都行,也可以绑定固定网卡上的ip地址
servaddr.sin_port = htons(2000);              // 0~1023:系统使用,1024以后用户可以使用
if (-1 == bind(socketfd, (struct sockaddr *)&servaddr, sizeof(struct sockaddr)))
{cout << "bind failed:" << strerror(errno) << endl;
}

2、实现监听

listen(socketfd, 10); //监听struct sockaddr_in clientaddr; //创建一个客户端用于接受数据
socklen_t len = sizeof(clientaddr);
cout<<"current socketfd:"<<socketfd<<endl;
int clientfd = accept(socketfd, (struct sockaddr*)&clientaddr, &len);
cout<<"clientfd is:"<<clientfd<<endl;
netstat -anop | grep 2000		#新建一个窗口,输入该命令查看绑定的2000端口状态,  22查ssh,3306查mysql,6309查redis

在这里插入图片描述

如果再开一个窗口执行监听,那么会报错
在这里插入图片描述

3、接受数据 fd与tcp连接,io通道建立成功

会一直阻塞等待数据的到来

char buffer[1024] = {0};
int count = recv(clientfd, buffer, 1024, 0);
cout<<"buffer:"<<buffer<<endl;

4、返回信息

count = send(clientfd, buffer,count, 0);

5、由于代码中只存在两个fd,socketfd和clientfd

当存在一个客户端连接服务端时,可以正常收发消息;但当出现多个客户端连接服务端时,只有一个客户端能发信息,其余
客户端不能发送信息
在这里插入图片描述

在这里插入图片描述

客户端发送消息结果:
在这里插入图片描述

在这里插入图片描述

小结:

虽然3个客户端都连接服务端成功,但最终通信成功的只有一个,acept就调用成功一次就结束了,自然就接收不到其余两个客户端的数据

优化代码:

在这里插入图片描述

while (true){cout<<"current socketfd:"<<socketfd<<endl;int clientfd = accept(socketfd, (struct sockaddr *)&clientaddr, &len);cout<<"clientfd is:"<<clientfd<<endl;char buffer[1024] = {0};int count = recv(clientfd, buffer, 1024, 0);cout << "buffer:" << buffer << endl;//返回信息count = send(clientfd, buffer, count, 0);}

小结:

虽然都通信成功,但只能发送一次消息,无法发送第二次消息,在acept这进行了阻塞,而且必须根据连接顺序来处理信息,
比如连接顺序是1号,2号,3号客户端,3号连发3次消息,2号连发2次消息,此时服务端仍然没反应,在等待1号发消息,
1号发消息,然后服务端依次处理,将2号的2次消息,3号的3次消息全部发出,然后阻塞,需要有新的连接,然后才能处理消息。

存在两个问题:

1、无法实时响应。
2、一次性连接处理信息问题

三、多个IO如何接收数据

1、解决实时性问题和一次性连接处理问题

当多个客户端连接服务器时,accept会进行阻塞,等待第一个用户数据接收完之后,才处理第二个用户的请求…

解决方案:

采用多线程来解决。

void *ClientPthread(void *arg)
{int clientfd = *(int *)arg;while(true){cout<<"clientfd is:"<<clientfd<<endl;char buffer[1024] = {0};int count = recv(clientfd, buffer, 1024, 0);cout << "buffer:" << buffer << endl;//返回信息count = send(clientfd, buffer, count, 0);}
}while (true){cout<<"current socketfd:"<<socketfd<<endl;int clientfd = accept(socketfd, (struct sockaddr *)&clientaddr, &len);pthread_t p_id;pthread_create(&p_id, NULL, ClientPthread, &clientfd);}

在这里插入图片描述

2、讨论fd的值

无论什么时候连接,或者多个客户端连接,发现socketfd的值永远是3,而接收客户端返回的fd却是在3的基础上+1
那么fd,0,1,2去哪了

ls /dev/fd

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

原来这三个值分别是代表标准输入,输出以及错误
那允许多少客户端连接呢,fd是个整数,肯定也存在一定的范围

ulimit -a

在这里插入图片描述

当前最多只支持到这么多

3、fd支持有限,那客户端断开连接后,原来的fd还能用吗?

答案是肯定的,系统有自己的回收策略

int count = recv(clientfd, buffer, 1024, 0);if(count == 0){                  //断开close(clientfd);            //必须要有close,不然系统不会回收fd资源break;}

在这里插入图片描述

http://www.xdnf.cn/news/518221.html

相关文章:

  • freertos智能时钟开发环境详细搭建指南:从零开始的freertos智能时钟学习之路
  • 180KHz 60V 5A开关电流升压/升降压型DC-DC转换器XL4019升降压芯片
  • 最新最热门的特征提取方式:CVOCA光学高速复值卷积
  • 【JavaWeb】JDBC
  • React响应事件中onClick={handleClick} 的结尾有没有小括号的区别
  • [ctfshow web入门] web119
  • C++实现伽罗华域生成及四则运算(二)
  • 小记录111
  • Day29
  • 基于Spring Cloud Sentinel自研Slot扩展实战
  • AI图像处理之ComfyUI节点(二)
  • CSS动画实现
  • React方向:react脚手架的使用
  • 【快速解决】彻底卸载VMWare
  • 2025.5.17总结
  • 时间服务器深度解析与实战指南:从原理到企业级部署
  • GO学习指南
  • INA226 高侧/低侧测量、双向电流/功率监视器,具有I2C兼容接口
  • 处理金融数据,特别是股票指数数据,以计算和分析RSRS(相对强度指数)
  • NE555双音门铃实验
  • 电子电路:阻抗是什么,容抗又是什么?
  • Python打卡 DAY 29
  • Baklib赋能企业知识资产AI化升级
  • Python 中二维列表(list)(嵌套列表)详解
  • 3Dmax中用RayFire实现破碎动画效果
  • Python黑魔法与底层原理揭秘:突破语言边界的深度探索
  • TensorRT
  • 提取YOLO检测框-以车牌识别为例
  • 远程文件传输解决方案:用群晖NAS Cloud Sync实现跨地区传输与多人同时传输时的优化
  • 什么是 Boosting