【网络编程】select和poll
select
select() 确定一个或多个套接口的状态,如:需要则等待。
#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软件中的兼容,但内部的表达是完全不同的。
//例子:
#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()函数同等功能的函数,下面是这个函数的声明:
#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描述符的情况;
//例子:
#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;
}
*
当你停下来休息的时候,不要忘记别人还在奔跑!