【网络编程】select和poll

select#

select() 确定一个或多个套接口的状态,如:需要则等待。

Copy Highlighter-hljs
#include <winsock.h> int PASCAL FAR select( int nfds, fd_set FAR* readfds, fd_set FAR* writefds, fd_set FAR* exceptfds, const struct timeval FAR* timeout); //参数说明: - nfds:是一个整数值,是指集合中所有文件描述符的范围,即所有文件描述符的最大值加1,不能错!在Windows中这个参数的值无所谓,可以设置不正确。 - readfds:(可选)指针,指向一组等待可读性检查的套接口。 - writefds:(可选)指针,指向一组等待可写性检查的套接口。 - exceptfds:(可选)指针,指向一组等待错误检查的套接口。 - timeout:select()最多等待时间,对阻塞操作则为NULL

select(),确定一个或多个套接口的状态,本函数用于确定一个或多个套接口的状态,对每一个套接口,调用者可查询它的可读性、可写性及错误状态信息,用fd_set结构来表示一组等待检查的套接口,在调用返回时,这个结构存有满足一定条件的套接口组的子集,并且select()返回满足条件的套接口的数目。有一组宏可用于对fd_set的操作,这些宏与Berkeley Unix软件中的兼容,但内部的表达是完全不同的。

Copy Highlighter-hljs
//例子: #include <iostream> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> using namespace std; int main() { int sock_listen=socket(AF_INET,SOCK_STREAM,0); int optval=1; setsockopt(sock_listen,SOL_SOCKET,SO_REUSEADDR,&optval,sizeof(optval)); sockaddr_in my_addr; my_addr.sin_family=AF_INET; my_addr.sin_addr.s_addr=INADDR_ANY; my_addr.sin_port=htons(8888); if(-1==bind(sock_listen,(sockaddr*)&my_addr,sizeof(my_addr))) { perror("bind()"); return 0; } listen(sock_listen,5); int sock_conn=accept(sock_listen,NULL,NULL); int retval; char msg[1025]; fd_set rfds;//设置结构体 while(1) { //宏 FD_ZERO(&rfds); FD_SET(0,&rfds); FD_SET(sock_conn,&rfds);//把套接字加入 retval=select(sock_conn+1,&rfds,NULL,NULL,NULL);//开始 if(retval<0) { perror("select()"); break; } if(FD_ISSET(0,&rfds)) { cin.getline(msg,sizeof(msg)); send(sock_conn,msg,strlen(msg),0); } if(FD_ISSET(sock_conn,&rfds)) { retval=recv(sock_conn,msg,sizeof(msg)-1,0); if(retval<=0) { cout<<"对方断开连接,通信结束!"<<endl; break; } else { msg[retval]='\0'; cout<<msg<<endl; } } } close(sock_conn); close(sock_listen); return 0; }

poll#

poll()函数:这个函数是某些Unix系统提供的用于执行与select()函数同等功能的函数,下面是这个函数的声明:

Copy Highlighter-hljs
#include <poll.h> int poll(struct pollfd fds[], nfds_t nfds, int timeout); //参数说明: - fds:是一个struct pollfd结构类型的数组,用于存放需要检测其状态的Socket描述符;

每当调用这个函数之后,系统不会清空这个数组,操作起来比较方便;特别是对于socket连接比较多的情况下,在一定程度上可以提高处理的效率;这一点与select()函数不同,调用select()函数之后,select()函数会清空它所检测的socket描述符集合,导致每次调用select()之前都必须把socket描述符重新加入到待检测的集合中;因此,select()函数适合于只检测一个socket描述符的情况,而poll()函数适合于大量socket描述符的情况;

Copy Highlighter-hljs
//例子: #include <iostream> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #include <poll.h> using namespace std; int main() { int sock_listen=socket(AF_INET,SOCK_STREAM,0); int optval=1; setsockopt(sock_listen,SOL_SOCKET,SO_REUSEADDR,&optval,sizeof(optval)); sockaddr_in my_addr; my_addr.sin_family=AF_INET; my_addr.sin_addr.s_addr=INADDR_ANY; my_addr.sin_port=htons(8888); if(-1==bind(sock_listen,(sockaddr*)&my_addr,sizeof(my_addr))) { perror("bind()"); return 0; } listen(sock_listen,5); int sock_conn=accept(sock_listen,NULL,NULL); int retval; char msg[1025]; struct pollfd fds[2]={{0,POLLIN},{sock_conn,POLLIN}}; while(1) { retval=poll(fds,2,-1); if(retval<0) { perror("poll()"); break; } if(fds[0].revents) { cin.getline(msg,sizeof(msg)); send(sock_conn,msg,strlen(msg),0); } if(fds[1].revents) { retval=recv(sock_conn,msg,sizeof(msg)-1,0); if(retval<=0) { cout<<"对方断开连接,通信结束!"<<endl; break; } else { msg[retval]='\0'; cout<<msg<<endl; } } } close(sock_conn); close(sock_listen); return 0; } *
posted @   快乐的提千万  阅读(4)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
点击右上角即可分享
微信分享提示
CONTENTS