FD_SET(pMFCServerDlg->m_sListen, &pMFCServerDlg->fdSocket); while( true )
{
// 2)将fdSocket集合的一个拷贝fdRead传递给select函数,
// 当有事件发生时,select函数移除fdRead集合中没有未决I/O操作的套节字句柄,然后返回。
fd_set fdRead = pMFCServerDlg->fdSocket;
if( 0 < select(0,&fdRead,NULL,NULL,NULL) )
{
// 3)通过将原来fdSocket集合与select处理过的fdRead集合比较,
// 确定都有哪些套节字有未决I/O,并进一步处理这些I/O。
for(int i = 0;i < (int)pMFCServerDlg->fdSocket.fd_count;i++)
{
//监听套接字收到新连接
if(FD_ISSET(pMFCServerDlg->fdSocket.fd_array[i], &fdRead))
{
if(pMFCServerDlg->m_sListen == pMFCServerDlg->fdSocket.fd_array[i])
{
SOCKADDR_IN addrRemote;
int nLen = sizeof(addrRemote);
SOCKET sNew = accept(pMFCServerDlg->m_sListen,(SOCKADDR*)&addrRemote,&nLen);
FD_SET(sNew,&pMFCServerDlg->fdSocket);
//pMFCServerDlg->showMsg(_T("系统消息:有客户端上线!"));
}
else
{
//接收数据
TCHAR recvBuf[256] = {0};
if(recv(pMFCServerDlg->fdSocket.fd_array[i],(char *)recvBuf,sizeof(recvBuf),0) > 0 )
{
//将TCHAR转换为CString
recvMsg = recvBuf;
//开始处理接收到的数据
pMFCServerDlg->DisposeRecvMsg(pMFCServerDlg->fdSocket.fd_array[i],recvMsg);
}
else
{
//关闭套接字
closesocket(pMFCServerDlg->fdSocket.fd_array[i]);
//从集合中删除该套接字
FD_CLR(pMFCServerDlg->fdSocket.fd_array[i],&pMFCServerDlg->fdSocket);
//提示有客户端已经离线!
strTemp = _T("系统消息->“");
strTemp = strTemp + pMFCServerDlg->m_ClientMap.GetAt(i-1).strName + _T("”离线!");
pMFCServerDlg->showMsg(strTemp);
//从客户端列表中删除该套接字和昵称
pMFCServerDlg->m_ClientMap.RemoveAt(i-1);
//因为客户端列表有变化,所以需要给所有当前在线客户端更新
pMFCServerDlg->sendClientMap();
//显示当前在线客户端数目
pMFCServerDlg->SetDlgItemInt(IDC_CLIENT_NUM,pMFCServerDlg->m_ClientMap.GetCount());
break;
} }
}
}
}网上找了一段代码,对其中有些不解。它是把监听句柄m_sListen加入到fdSocket中,FD_SET(pMFCServerDlg->m_sListen, &pMFCServerDlg->fdSocket);我想知道fdSocket集合中都是什么东西。按我的理解是就一个listen句柄,怎么他后面还用到了遍历,难道是很多东西?for(int i = 0;i < (int)pMFCServerDlg->fdSocket.fd_count;i++)。

解决方案 »

  1.   

    FD_SET(pMFCServerDlg->m_sListen, &pMFCServerDlg->fdSocket); 
    这句是加入监听套接字
    m_sListen、fdSocket两者是不同类型的
    m_sListen是Socket套接字  
    fdSocket是FD_SET套接字集合fd_set是一个管理多个套接字的结构体
    这个是select()模型的特点。
    当你调用select()函数对套接字进行监视的之前,应用程序必须将套接字分配给一个集合。设置可读、可写、以及列外的fd_set结构,然后调用select函数就可以知道那些套接字是否发生I/O操作。for(int i = 0;i < (int)pMFCServerDlg->fdSocket.fd_count;i++)。
    由于fdSocket是FD_SET套接字集合,所以需要判断每个套接字是否可读(dRead);
      

  2.   

    看了楼上的解释还是有点不明白。FD_SET(pMFCServerDlg->m_sListen, &pMFCServerDlg->fdSocket);  是将监听套接字加入到fdSocket的集合中,就跟往carray中添加元素一样,我认为只是将一个监听套接字加入了,那为什么后面还用遍历,直接用那一个m_sListen不就行了吗。我还是不明白fdsocket中存放的是什么。
      

  3.   

    select函数返回会修改每个fdsocket套接字,
    fdsocket中存放着程序运行后服务端所接收客户度的一系列的套接字;
    这些套接字的状态可能各不一样
    有的是可读的 有的是可写的 有的处于监听状态的
      

  4.   

    遍历是因为不停的调用select函数
    fdsocket存在了N多不同状态的套接字
    所以需要去循环 并判断每个套接字的状态