在网络协议实现时,在很多时候,我方在特定时刻并不清楚对方会进行怎样的操作,是发送数据、发起连接、关闭连接还是什么也不做。此时在程序中我们采用的第一种方法是循环检测:
while(TRUE)
{
if(recv()>0)
{
…
}
if(accept()!=SOCK_ERR)
{
…
}
}
当然这种方法是可以的,但是必须注意的是最好采用非阻塞模式运行recv()、accept(),因为如果是阻塞模式在recv()和accept()中会阻塞,此时如果正运行recv()则无法立即响应接受连接,如果正运行accept()则无法立即接收数据。
实际上,ZLIP提供了灵活的机制方便进行复杂的网络协议编程,这些机制包括:
1. 使用select函数编程。
2. 使用类MFC回调机制。
3. 在us/os-II中使用ZLIP。
这里先介绍第一种:使用select函数编程。select()提供了同时检测多个套接字状态的机制,只要其中的一个套接字发生了预期的收到数据、接受连接、被关闭事件后,select()会立即返回,返回后用户可以检测是哪个套接字发生了事件,并做相应的处理。实例程序test_complex_send_recv就是使用select函数编程的典型例子。使用select()编程有如下的固定模式:
while(TRUE)
{
/* 清空测试集,准备开始新的检测 */
FD_ZERO(&r);
FD_ZERO(&w);
/* 将需要检测的套接字放入读测试或写测试集中 */
FD_SET(sc[0], &w);
FD_SET(sc[0], &r);
FD_SET(sc[1], &w);
FD_SET(sc[1], &r);
/* 等待相应的事件发生 */
select(0, &r, &w, NULL, NULL);
/* 是否为sc[0]可读*/
if(FD_ISSET(sc[0], &r))
{
…
}
/* 是否为sc[0]可写*/
if(FD_ISSET(sc[0], &w))
{
…
}
/* 是否为sc[1]可读*/
if(FD_ISSET(sc[1], &r))
{
…
}
/* 是否为sc[1]可写*/
if(FD_ISSET(sc[1], &w))
{
…
}
}