转自:http://hi.baidu.com/beibeiboo/blog/item/3868b2fcc8d80df5fc037ffd.html
关于select函数:
其函数原型为:
int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
此函数的功能是由内核检测在timeout时间内,是否有readfds,writefds,exceptfds三个句柄集(file descriptors)里的某个句柄(file descriptor)的状态符合寻求,即readfds句柄集里有句柄可读或writefds句柄集里有可写或exceptfds句柄集里有例外发生,任何一个有变化函数就立即返回,返回值为timeout发生状态变化的句柄个数。
n是所有readfds,writefds,exceptfds三个句柄集(file descriptors)里编号最大值加1。比如:要检测两个socket句柄fd1和fd2在timeout时间内是否分别可读和可写就可以这样:
先把两个句柄集(file descriptors)清零:
FD_ZERO (&readfds);
FD_ZERO (&writefds);
然后把fd1加入读检测集:
FD_SET (fd1, &readfds);
然后把fd2加入写检测集:
FD_SET (fd2, &writefds);
再给timeout设置值,timeout是这样的一个结构:
struct timeval {
long tv_sec; /* seconds */
long tv_usec; /* microseconds */
};
你可以这样赋值:
timeout.tv_sec=1;
timeout.tv_uec=0;
表示检测在1秒钟内是否有句柄状态发生变化。
如果有句柄发生变化,就可以用FD_ISSET检测各个句柄,比如:
FD_ISSET (fd1, &readfds);//检测是否fd1变成可读的了
FD_ISSET (fd2, &writefds);//检测是否fd2变成可写的了
示意程序代码如下:
/*----------------------示意代码开始--------------------------------------------*/ fd1 = socket();//创建一个socket fd2 = socket();//创建一个socket while(1) { FD_ZERO (&readfds); FD_ZERO (&writefds); FD_SET (fd1, &readfds); FD_SET (fd2, &writefds); timeout.tv_sec=1; timeout.tv_uec=0; ret = select(fd1>fd2?(fd1+1):(fd2+1), &readfds, &writefds, NULL, &timeout); if(ret < 0) {printf("系统错误,select出错,错误代码:%d, 错误信息:%s", errno, strerror(errno));} else if(ret == 0) {printf("select超时返回,没有任何句柄状态发生变化!");} //有句柄状态发生了变化 if(FD_ISSET(fd1, &readfds)) { fd1有数据可读; fd1里的数据被读出来; } if(FD_ISSET(fd2, &writefds)) { fd2可写; fd2里发送数据给对方; } } /*----------------------示意代码结束--------------------------------------------*/ |
1、开启监听的函数
/*----------------------源代码代码开始--------------------------------------------*/ ret = sockfd = socket(PF_INET, SOCK_STREAM, 0); ret = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuseORnot, sizeof(int)); ret = setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &recvbuflen, sizeof(int)); ret = setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, &sendbuflen, sizeof(int)); ioctl(sockfd,FIONBIO,&blockORnot);/*block or not*/ laddr.sin_family = PF_INET; ret = bind(sockfd, (struct sockaddr *)&laddr, sizeof(struct sockaddr)); |
/*----------------------源代码代码开始--------------------------------------------*/ if((he=gethostbyname(serverip))== 0) { serversock = socket(PF_INET, SOCK_STREAM, 0); ioctl(serversock, FIONBIO, &blockORnot); //block or not memset((char*)&sin, 0, sizeof(struct sockaddr_in)); ret = connect(serversock, (struct sockaddr *)&sin, sizeof(sin)); if(ret == -1) { return serversock; |
/*----------------------源代码代码开始--------------------------------------------*/ struct timeval tival; tival.tv_sec = timeout; FD_ZERO(&writefds); if(sock > 0) { ret = select(maxfds + 1, NULL, &writefds, NULL, &tival); while(i < size) { if (EINTR == errno) close(sock); |
/*----------------------源代码代码开始--------------------------------------------*/ struct timeval tival; tival.tv_sec = timeout; FD_ZERO(&readfds); if(sock > 0) { ret = select(maxfds + 1, &readfds, NULL, NULL, &tival); |