Linux网络编程——多路IO转接服务器设计

news/2023/6/7 0:21:37

文章目录

  • select多路IO转接:
  • 思路分析
  • 代码实现
  • select优缺点:


select多路IO转接:

  • 原理:借助内核,select来监听,客户端连接、数据通信事件。

     void FD_ZERO(fd_set *set);  ---清空一个文件描述符集合fd_set rset;FD_ZERO(&rset);void FD_SET(int fd, fd_set *set);    ---将待监听的文件描述符,添加到监听集合中FD_SET(3,&rset);FD_SET(5,&rset) ;FD_SET(6,&rset);void FD_CLR(int fd, fd_set *set);    --将一个文件描述符从监听集合中移除。FD_CLR(4,&rset); int FD_ISSET(int fd, fd_set *set);    ---判断一个文件描述符是否在监听集合中。返回值:在:1;不在。0;FD_ISSET (4,&rset) ;
    
  • int select(int nfds,fd_set *readfds,fd_set *writefds, fd_set *exceptfds,struct timeva1 *timeout);

    nfds:监听的所有文件描述符中,最大文件描述符+1
    readfds: 读文件描述符监听集合。传入、传出参数
    writefds: 写文件描述符监听集合。传入、传出参数 NULL
    exceptfds: 异常文件描述符监听集合。传入、传出参数NULL
    timeout: >0:设置监听超时时长。NULL:阻塞监听。0:非阻塞监听,轮询
    返回值:>0:所有监听集合(3个)中,满足对应事件的总数。0:没有满足监听条件的文件描述符。-1:errnol

思路分析

lfd = socket() ;			创建套接字
bind() ;					绑定地址结构
listen();					设置监听上限
fd_set rset,allset;		创建r监听集合
FD_ZERO(&allset);			将r监听集合清空
FD_SET(lfd, &allset);		将lfd 添加至读集合中。
while (1){rset = a11set;			保存监听集合ret = select(lfd+1,&rset,NULL,NULL,NULL);		监听文件描述符集合对应事件。if (ret > 0){				有监听的描述符满足对应事件if (FD_ISSET(lfd,&rset)){			// 1在。0不在。cfd = accept () ﹔					建立连接,返回用于通信的文件描述符FD_SET(cfd,,&allset);			添加到监听通信描述符集合中。}for (i = lfd+1;i <=最大文件描述符; i++){FD_ISSET(i,&allset)				有read、write事件read ()小-大write();}}
}

代码实现

服务端:

#define SERV_PORT 6666
int main(int argc,char *argv[]){int i, j,n,nready;int maxfd = 0;int listenfd,connfd;char buf[BUFSIZ];		/*#define INET_ADDRSTRLEN 16*/struct sockaddr_in clie_addr , serv_addr;socklen_t clie_addr_len;listenfd = Socket(AF_INET,SOCK_STREAM,0);int opt = 1;setsockopt(listenfd,soL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));bzero(&serv_addr , sizeof(serv_addr));serv_addr.sin_fanily= AF_INET;serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);serv_addr.sin_port= htons(SERV_PORT);Bind(listenfd,(struct sockaddr * )&serv_addr , sizeof(serv_addr));Listen(listenfd,128);fd_set rset,allset; 		/*set 读事件文件描述符集合allset用来暂存*/maxfd = listenfd;FD_ZERO(&allset);FD_SET(listenfd,&allset);	/*构造select监控文件描述符集*/while (1){rset = allset;			/*每次循环时都从新设置select监控信号集*/nready = select(naxfd+1&rset,NULL,NULL,NULL);if (nready < 0)perr_exit( "select error");if (FD_ISSET(listenfd,&rset)) {		/*说明有新的客户端链接请求*/clie_addr_len = sizeof(clie_addr);connfd = Accept(listenfd,(struct sockaddr * )&clie_addr,&clie_addr_len);			/* Accept不会阻塞*/FD_SET(connfd,&allset);		/*向监控文件描述符集合allset添加新的文件描述符connfd*/if (naxfd < connfd)maxfd = connfd;if (0 == --nready)			/*只有listenfd有事件,后续的for不需执行*/continue;}for (i = listenfd+1; i <= naxfd; i++) {		/*检测哪个clients有数据就绪*/if (FD_ISSET(i,&rset)) {if ((n = Read(i,buf,sizeof(buf))) == 0)		/*当client关闭链接时,服务器端也关闭对应链接*/close(i);FD_CLR(i, &allset);					/*解除select对此文件描述符的监控*/}else if (n > 0) {for (j = 0; j <n; j++)buf[j] = toupper(buf[j]);write(i, buf, n);}}}}return 0;
}	

客户端:

int main(int argc,char *argv[]){struct sockaddr_in servaddr;char buf[MAXLINE];int sockfd,n;sockfd = Socket(AF_INET,SOCK_STREAM,0);bzero(&servaddr ,sizeof(servaddr ));servaddr.sin_fanily = AF_INET;inet_pton(AF_INET,"127.0.0.1",&servaddr.sin_addr.s_addr);servaddr.sin_port = htons(SERV_PORT);Connect(sockfd,(struct sockaddr *)&servaddr ,sizeof(servaddr));printf("---------- --connect ok----------------\n");while (fgets(buf,MAXLINE,stdin) != NULL){write(sockfd,buf, strlen(buf));n = Read(sockfd,buf,MAXLINE);if (n == 0) {printf( "the other side has been closed.\n");break;}elsewrite(STDOUT_FILENO,buf,n);}close(sockfd);return 0;
}

select优缺点:

缺点:
监听上限受文件描述符限制。最大1024.
检测满足条件的fd,自己添加业务逻辑提高小。提高了编码难度。

优点:
跨平台。win、linux、macOS、Unix、类Unix、mips

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.exyb.cn/news/show-4553861.html

如若内容造成侵权/违法违规/事实不符,请联系郑州代理记账网进行投诉反馈,一经查实,立即删除!

相关文章

【易语言组合框和列表框联动】

添加组合框和列表框联动 右击组合框选择设置项目 列表框添加组合框得选中项 列表框1.加入项目 (组合框1.内容, )列表框双击删除内容 列表框1.删除项目 (列表框1.现行选中项)组合框和组合框联动 没啥写的 就是if判断和组合框清空与加入项目的方法 组合框3.清空 () .判断开…

易语言读取计算机配置,易语言取所有配置节名和配置项名

本视频教程演示了取配置节名称、取配置项名称、取所有配置节和所有配置项名称&#xff0c;通过了精易模块和多种方法来实现。视频链接&#xff1a;511遇见易语言教程教程源码:.版本 2.支持库 spec.程序集 窗口程序集_启动窗口.子程序 _按钮1_被单击.局部变量 序号, 整数型.如果…

易语言mysql清空一个表_易语言遍历和删除sqlite数据库信息方法

易语言如何遍历和删除sqlite数据库信息呢1、打开易语言&#xff0c;我们新建一个“Windows”窗口程序&#xff0c;进入到窗口程序集中2、在新建的窗口中添加2个编辑框&#xff0c;1个按钮组件。并修改组件的属性。3、我们双击启动窗口&#xff0c;在__启动窗口_创建完毕程序中&…

易语言快照和截取屏幕区域

本课录制了两个和截图有关的易语言命令&#xff0c;快照和截取屏幕区域&#xff0c;并且分快照窗口快照&#xff0c;全屏快照&#xff0c;保存快照&#xff0c;已经截屏区域等等。 视频链接&#xff1a; 511遇见易语言教程一、快照&#xff08;&#xff09; 主要用于截图 1、…

数据结构 - 学习笔记 - 红黑树前传——234树

数据结构 - 学习笔记 - 红黑树前传——234树简介结点类型与红黑树对应关系插入逻辑插入步骤演示2结点插入3结点插入&#xff08;红黑树旋转&#xff09;共对应6种红黑树情形有4种情形需要再平衡4结点插入&#xff08;红黑树变色&#xff09;234树转红黑树触发分裂有4种情形需要…

求一元二次方程的根【C++】

哈哈哈这个就图一乐&#xff0c;各位看官要铭记&#xff0c;眼过千遍不如手过一遍 求一元二次方程axbxc0&#xff08;a≠0&#xff09;的根 求根公式哦一元二次方程的求根公式是什么&#xff1f;_百度知道 #include<iostream> #include<cmath> using namespace s…

c语言怎样调用求根函数,编写函数求一元二次方程的根,并在main主函数中调用该函数 用c++编写...

满意答案sIXzVDhc2014.01.10采纳率&#xff1a;58% 等级&#xff1a;12已帮助&#xff1a;7410人#include #include void b1 (){float l,s,k;int a,b,c,h;printf ("************这是求根方程****************\n");printf("\n");printf("输入a,b,c的…