linuxselectsocket
‘壹’ linux socket编程、server端有几个socket绑定不同端口、想用select函数实
fd_set rdfds; /* 先申明一个 fd_set 集合来保存我们要检测的 socket句柄 */
struct timeval tv; /* 申明一个时间变量来保存时间 */
int ret; /* 保存返回值 */
FD_ZERO(&rdfds); /* 用select函数之前先把集合清零 */
FD_SET(socket, &rdfds); /* 把要检测的句柄socket加入到集合里 */
tv.tv_sec = 1;
tv.tv_usec = 500; /* 设置select等待的最大时间为1秒加500毫秒 */
ret = select(socket + 1, &rdfds, NULL, NULL, &tv); /* 检测我们上面设置到集合rdfds里的句柄是否有可读信息 */
if(ret < 0) perror("select");/* 这说明select函数出错 */
else if(ret == 0) printf("超时\n"); /* 说明在我们设定的时间值1秒加500毫秒的时间内,socket的状态没有发生变化 */
else { /* 说明等待时间还未到1秒加500毫秒,socket的状态发生了变化 */
printf("ret=%d\n", ret); /* ret这个返回值记录了发生状态变化的句柄的数目,由于我们只监视了socket这一个句柄,所以这里一定正大ret=1,如果同时有多个句柄举陵竖发生变化返回的就是句柄的总和了 */
/* 这里我们就应该从socket这个句柄里读取数据了,因为select函数已经告诉我们这个句柄里有数据可读 */
if(FD_ISSET(socket, &rdfds)) { /* 先判断一下socket这外被监视的句柄是否真的变成可读的了 */
/* 读取socket句汪贺柄里的数据 */
recv(...);
}
}
‘贰’ Linux网络编程:select函数的用法和原理
在Linux网络编程中,select函数扮演着关键角色,它的主要功能是检测一组socket中是否有事件就绪。具体来说,这些事件可以分为三类。
select()函数的用法如下:
参数说明:
其定义如下:
参数readfds,writefds,exceptfds的类型都是fd_set,这是一个结构体信息。
定义如下:
假设未定义__USE_XOPEN整理一年
将一个fd添加到fd_set这个集合中时需要使用FD_SET宏,其定义如下:
实现如下:
__FD_SET (fd, fdsetp)实现如下:
举个例子,假设现在fd的值为43,那么在数组下表为0的元素中第43个bit被置为1。
在Linux上,向fd_set集合中添加新的fd时,采用位图法确定位置;而在Windows中,添加fd至fd_set的实现规则依次从数组第0个位置开始向后递增。
也就是说,FD_SET宏本质上是在一个有1024个连续bit的数组的第fd位置置1。
同理,FD_CLR删除一个fd的原理,也就是将数组的第fd位置置为0。
实例:
使用nc -v 127.0.0.1 3000来模拟客户端,打开三个终端。
关于以上代码,需要注意以下几点:
windows上的socket函数
在Windows上,select函数结束后,不会修改timeval函数。