非阻塞通信之select模型

本文介绍了套接字的Select模型在Windows Sockets中的应用,通过调用select()函数来管理多个套接字状态,判断其可读可写性。详细讲解了fd_set结构体、timeval结构体及其相关宏的使用,帮助理解如何实现非阻塞通信。

    套接字的Select模型,能够使Windows Sockets应用程序同时对多个套接字进行管理。调用select()函数检查当前各个套接字的状态,并且根据套接字函数的返回值判断套接字的可读可写性。然后调用相应的windows sockets API,完成数据的发送、接收。

    select函数:

	int select(int maxfdp,fd_set *readfds,fd_set *writefds,fd_set *errorfds,struct timeval *timeout);
	
<span style="white-space:pre">	</span>//int maxfdp windows平台下没用,可忽略
	
<span style="white-space:pre">	</span>//fd_set *readfds 可读性套接字集合指针
	
<span style="white-space:pre">	</span>//fd_set *writefds可写性套接字集合指针
	
<span style="white-space:pre">	</span>//fd_set *errorfds检查错误套接字集合指针
	
<span style="white-space:pre">	</span>//timeval *timeout  select函数的等待时间

1.fd_set

    fd_set是一个管理多个套接字的结构体。在改结构体中,fd_count字段指明套接字的数量,fd_array字段保存fd_count个套接字。fd_set最多可以管理64个套接字。在程序中使用该结构表示一系列特定套接字的集合。例如,准备接收数据的套接字集合,称为可读性集合。准备发送数据的套接字集合,称为可写性集合。fd_set结构声明如下:

#define   FD_SETSIZE       64

typedef struct fd_set {

   u_int   fd_count;
 
   Socket  fd_array[FD_SETSIZE];

} fd_set;


2.timeval

     timeval结构体用于定义select()函数的等待时间。tv_sec 字段指定等待秒数,tv_usec字段指定等待毫秒数。

3.宏

     为了方便开发者的使用,windows sockets提供了下列宏,可用来针对I/O活动,对fd_set结构进行处理与检查。

     FD_CLR( s , * set ) ; 从set集合中删除s套接字;

     FD_ISSET( s , * set ) ; 检查s是否为set集合的一名成员。如果s是set集合的一名成员则返回TRUE;

     FD_SET( s , * set ) ;将套接字s加入set集合;

     FD_ZERO( * set ) ;将set集合初始化为空集合。


select同时处理两个可读套接字代码:

void CALLBACK EXPORT RT_Recv(HWND hWnd, UINT nMsg, UINT nIDEvent, DWORD dwTime)
{
	struct sockaddr_in Comsockaddr;
	int Number,sa;
	char buffer[50];	
	memset(buffer,0,50);
	memset(&Comsockaddr,0, sizeof(struct sockaddr_in));
	
	sa=sizeof(struct sockaddr_in);	
	fd_set read;
	timeval TimeOut;  
	TimeOut.tv_sec =1;
	TimeOut.tv_usec = 0;	//select()函数的等待时间
	
	while(1)
	{
		FD_ZERO(&read);
		FD_SET(recv_socket1, &read);//可读套接字1
		FD_SET(recv_socket2, &read);//可读套接字2
		if(select(1, &read, NULL, NULL, &TimeOut)!=1) return;//无信号则返回,上层函数会再一次调用RT_Recv函数

		if (FD_ISSET(recv_socket1,&read))
		{
			Number = recvfrom(recv_socket1,buffer,sizeof(buffer),0,(struct sockaddr FAR*)&Comsockaddr,&sa);
			if (Number>0)
			{
				AfxMessageBox("recv_socket1 receive data !");
			}
		
		}
		if (FD_ISSET(recv_socket2,&read))
		{
			Number = recvfrom(recv_socket2,buffer,sizeof(buffer),0,(struct sockaddr FAR*)&Comsockaddr,&sa);
			if (Number>0)
			{
				AfxMessageBox("recv_socket2 receive data !");
			}
			
		}
		
	}
	return;	//上次函数会再一次调用RT_Recv函数
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值