本帖最后由 VisualEleven 于 2012-07-30 07:44:09 编辑

解决方案 »

  1.   

    对网络编程不是很在行
    就从我对代码的理解角度分析下吧
    问题1:
    如果你的只读套接字set只被AcceptThread线程中的FD_SET(newAddrin,&newSocket)访问
    且你的在线客户端都是通过这个FD_SET来添加的话,那集合的结构体成员个数是在线的客户端的个数
    问题2:
    这个得等专家来解释了,不敢乱讲
      

  2.   

    刚收到你的私信,我看了你的代码。首先,你不太了解select模型呀。建议多看看模型原理
    不懂原理直接干活会头疼的select都不做返回直判断,你怎么判断套接字到底可不可用。问题点太多,很多知识需要补。
    http://blog.csdn.net/yanheifeng715000/article/details/6592447
      

  3.   

    这样做ok了吧朋友//接受线程
    unsigned int _stdcall ReveiveThread(void*)
    {while(1)
    {
    //raii锁
    select(NULL,&只读集合,NULL,NULL,时间); //剩下的套接字是在线的,和监听套接字          
    for(int i=0; i<只读集合体的个数;i++)        //
    {
    if(套接字==监听套接字)
    continue;
    char buf[2000];
    ::ZeroMemory(buf,sizeof(buf);
    //只能通过轮训的方式,去查找哪一个套接字接受了数据
    int nRet=revc(套接字集合[ i],buf,sizeof(buf)); //已经变成了非堵塞if(nRet!=0) //说明该套接字收到了客户端的数据
    {//解包
    并且去map中查找该套接字,查找后,更新map中的该套接字的最新会话时间}
    } //end for} //end while}
      

  4.   

    selcet 是把有数据的socket留在set中,没有的从set中删掉。select(.., &只读集合, ...)
    for ()
    {
       if (FD_ISSET(socket, &只读集合))
       {
          //有数据
       }
       else
       {
         //没有数据
       }
    }
      

  5.   


    真的假的啊, 我以为它的作用是去掉断线的socket
    照这样的话
    加入服务器连接10个客户端,他们都没掉线就一个客户端和服务器通信,其他一依然连接,那9个客户端会被select去掉吗?
      

  6.   

    不是掉线 是select的时候有数据过来了,被去掉的只不过没数据而已。
      

  7.   

    多谢,总结一下:有新的连接,和 有数据发送到服务器select后>=1,附一段网上的代码,这代码很多博客,文章都转载过, 我是菜鸟,觉得有些不对,高手莫笑,望指点1.fdSocket是没select前的集合,代码没对fdSocket select,所所以其的套接字数目不变。fdRead 则可能减少,也可能增多(比如:有新的连接)
    所以for循环的执行次数,就不该用fdSocket ,而改用fdRead .
     if(FD_ISSET(fdSocket.fd_array[i], &fdRead)) 这一句改成: if(FD_ISSET(fdRead.fd_array[i], &fdSocket))   if(fdSocket.fd_array[i] == sListen)        // (1)监听套节字接收到新连接这一句改成:   if(fdRead.fd_array[i] == sListen)        // (1)监听套节字接收到新连接(fdRead是处理过剩下有连接或者有数据的套接字)while(TRUE)
    {
        // 2)将fdSocket集合的一个拷贝fdRead传递给select函数,
        // 当有事件发生时,select函数移除fdRead集合中没有未决I/O操作的套节字句柄,然后返回。
        fd_set fdRead = fdSocket;
        int nRet = ::select(0, &fdRead, NULL, NULL, NULL);
        if(nRet > 0)
        {
            // 3)通过将原来fdSocket集合与select处理过的fdRead集合比较,
            // 确定都有哪些套节字有未决I/O,并进一步处理这些I/O。
            for(int i=0; i<(int)fdSocket.fd_count; i++)
            {
                if(FD_ISSET(fdSocket.fd_array[i], &fdRead))
                {
                    if(fdSocket.fd_array[i] == sListen)        // (1)监听套节字接收到新连接
                    {
                        if(fdSocket.fd_count < FD_SETSIZE)
                        {
                            sockaddr_in addrRemote;
                            int nAddrLen = sizeof(addrRemote);
                            SOCKET sNew = ::accept(sListen, (SOCKADDR*)&addrRemote, &nAddrLen);                        FD_SET(sNew, &fdSocket);
                            printf("接收到连接(%s)\n", ::inet_ntoa(addrRemote.sin_addr));
                        }
                        else
                        {
                            printf(" Too much connections! \n");
                            continue;
                        }
                    }
                    else
                    {
                        char szText[256];
                        int nRecv = ::recv(fdSocket.fd_array[i], szText, strlen(szText), 0);
                        if(nRecv > 0)                        // (2)可读
                        {
                            szText[nRecv] = '\0';
                            printf("接收到数据:%s \n", szText);
                        }
                        else                                // (3)连接关闭、重启或者中断
                        {
                            ::closesocket(fdSocket.fd_array[i]);
                            
                            printf("关闭\n");
                            FD_CLR(fdSocket.fd_array[i], &fdSocket);
                        }
                    }
                }
            }
        }
        else
        {
            printf(" Failed select() \n");
            break;
        }
    }while(TRUE)
    {
        // 2)将fdSocket集合的一个拷贝fdRead传递给select函数,
        // 当有事件发生时,select函数移除fdRead集合中没有未决I/O操作的套节字句柄,然后返回。
        fd_set fdRead = fdSocket;
        int nRet = ::select(0, &fdRead, NULL, NULL, NULL);
        if(nRet > 0)
        {
            // 3)通过将原来fdSocket集合与select处理过的fdRead集合比较,
            // 确定都有哪些套节字有未决I/O,并进一步处理这些I/O。
            for(int i=0; i<(int)fdSocket.fd_count; i++)
            {
                if(FD_ISSET(fdSocket.fd_array[i], &fdRead))
                {
                    if(fdSocket.fd_array[i] == sListen)        // (1)监听套节字接收到新连接
                    {
                        if(fdSocket.fd_count < FD_SETSIZE)
                        {
                            sockaddr_in addrRemote;
                            int nAddrLen = sizeof(addrRemote);
                            SOCKET sNew = ::accept(sListen, (SOCKADDR*)&addrRemote, &nAddrLen);                        FD_SET(sNew, &fdSocket);
                            printf("接收到连接(%s)\n", ::inet_ntoa(addrRemote.sin_addr));
                        }
                        else
                        {
                            printf(" Too much connections! \n");
                            continue;
                        }
                    }
                    else
                    {
                        char szText[256];
                        int nRecv = ::recv(fdSocket.fd_array[i], szText, strlen(szText), 0);
                        if(nRecv > 0)                        // (2)可读
                        {
                            szText[nRecv] = '\0';
                            printf("接收到数据:%s \n", szText);
                        }
                        else                                // (3)连接关闭、重启或者中断
                        {
                            ::closesocket(fdSocket.fd_array[i]);
                            
                            printf("关闭\n");
                            FD_CLR(fdSocket.fd_array[i], &fdSocket);
                        }
                    }
                }
            }
        }
        else
        {
            printf(" Failed select() \n");
            break;
        }
    }