关闭

SELECT 入门详解

863人阅读 评论(0) 收藏 举报

        在winsock的编程中,winsock有许多阻塞函数。比如:accept,recv等。线程执行到这个函数时就会挂起,等条件满足时再继续执行。比如,服务器端accept,只有当客户端执行connect时,才会接着往下执行。而使用select模型,进行通信,可以避免线程挂起,减少资源消耗。select模型,使用范围很广,通常用作网络通讯的客户端,或者连接数较小的服务端,如局域网游戏。

        select模型要用的结构和函数如下:

        fd_set,可以理解为文件句柄的一个集合,sock也可认为是一个文件句柄。

        timeval,用来表示时间,结构体中的tv_sec表示秒,tv_usec表示毫秒。

        int select(int maxfdp,fd_set *readfds,fd_set *writefds,fd_set *errorfds,struct timeval *timeout); 通过这个函数进行查询,返回值是所有socket的数目,这些socket包含在fd_set结构中,并且已完成准备工作。如果超时,则返回0,如果出错,则返回SOCKET_ERROR。

        使用过程一般遵循以下步骤:

       1、声明FD_SET变量

       2、初始化FD_SET变量

       3、关联文件句柄和FD_SET变量

       4、设置超时时间。

       5、调用select看是否有可用的socket

       6、调用FD_ISSET看究竟是哪个socket可用,对这个socket进行进一步操作。

      源码如下:(或者见http://download.csdn.net/detail/cloud95/4186484

while(TRUE) 
{ 
	printf("nRetCode!=SOCKET_ERROR) while(TRUE)\t"); 
	FD_SET writefd; 
	FD_SET readfd; 
	FD_ZERO(&writefd); 				 //初始化 
	FD_ZERO(&readfd); 
	FD_SET(ClientSocket,&writefd);   //关联FD_SET结构和文件句柄
	FD_SET(ServerSocket,&readfd); 
	timeval timeout={3,0};          //select等待3秒,3秒轮询,要非阻塞就置0
	nRetCode=select(0, &writefd, &readfd, NULL, &timeout); 
	if(SOCKET_ERROR==nRetCode) 
	{ 
		printf("Select错误"); 
		return  nRetCode ; 
	} 
    else if(nRetCode>0) 
	{ 
		if(FD_ISSET(ClientSocket,&writefd)) //测试sock是否可写,数据是来自哪个socket,其实对于非阻塞函数一般不做判断
		{ 
			printf("writefd启动"); 
			if(FALSE ==SendData(ServerSocket))//发送数据接收数据 
			{	 
				printf("SendData(ServerSocket)未成功");   
				return 0; 
			} 
		} 
		if(FD_ISSET(ServerSocket,&readfd)) //测试sock是否可读,数据是来自哪个socket, 
		{ 
			printf("readfd启动\n"); 
			if (FALSE == RecvData(ServerSocket)) //接收数据 
			{ 
				printf("RecvData(ServerSocket)失败"); 
				return 0; 
			} 
		} 
	}
}


 

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:271430次
    • 积分:4320
    • 等级:
    • 排名:第6972名
    • 原创:180篇
    • 转载:0篇
    • 译文:4篇
    • 评论:30条
    最新评论