我学习socket编程还处于初级阶段,最近被select困扰了很久,有个问题与大家讨论。
我原来的用法是在一个线程中反复select查询socket状态:
while (pDlg->m_bGo)
{
status = select(0,&m_ReadFds,NULL,NULL,&timeout);
switch(status)
{
case SOCKET_ERROR:
break;
case 0:
     break;
default:
if (FD_ISSET(m_Socket,&m_ReadFds))
{
}
     break;
}
}
遇到的问题是第一次能成功select,循环到第二次select就发生SOCKET_ERROR,错误代码10022(Invalid argument)。调试发现第二次循环走过select后,m_ReadFds.fd_count等于0,推断是此线程之外的其他某个操作造成这样的异常。在排除了任何其他可能后,最终确定敏感事件集FD_SET需要在每次select之前都设置一次,而不是设置一次后select多次。也就是插入一行:
while (pDlg->m_bGo)
{
                FD_SET(m_Socket,&m_ReadFds);
status = select(0,&m_ReadFds,NULL,NULL,&timeout);
switch(status)
                ……
         }
为什么socket要设计成这样一种模式?我觉得完全可以第一次设置敏感事件集FD_SET,以后不再需要维护,这样不是能节省一些开销吗?对此处的设计原理有些不解。

解决方案 »

  1.   

    windows的异步窗口模式可以实现你想象的功能,不过是以窗口消息的方式实现的,不适合高性能应用
      

  2.   

    select函数本来就有一个水平触发还是边缘触发的选择,可惜windows选择的是边缘触发。
    可能是windows有它自己专门的高性能网络模式。
    具体也不是特别清楚,呵呵
    权当抛砖引玉了。
      

  3.   

    select可以用于查询多个SOCKET的状态,它的强项就是在于多个SOCKET
    因此它的返回结果必须用集合来实现,也就是说每次必须将感兴趣的SOCKET添加到这个集合中你这里的情况只是对一个SOCKET进行查询,可以改用WSAEventSelect来查询
      

  4.   


    是的,有的时候我们并没有窗口,所以这部分功能就浪费了。
    我的本意是模拟WSAEventSelect的功能,定制自己的接口。