18,355
社区成员
发帖
与我相关
我的任务
分享
问题在代码注释中
2个线程函数,第一个是accept套接字
第二个是接受数据线程
unsigend int _stdcall AcceptThread(void*)
{
while(1)
{
select(0,只读套接字集合,NULL,NULL,NULL); //最后一个参数为NULL,表示阻塞
SOCKET newSocket;
socketaddr_in newAddrin; //新地址
int nAddLen=sizeof(newSocket);
newSocket=accept(sListen,(sockaddr*)&newAddrin,&nAddLen);
//添加到只读集合中
FD_SET(newAddrin,&newSocket);
}
return 0;
}
//接受线程
unsigned int _stdcall ReveiveThread(void*)
{
while(1)
{
//raii锁
select(NULL,&只读集合,NULL,NULL,NULL); //最后一一个参数不用NULL,改成timeval 结构体,设置时间
for(int i=0; i<只读集合体的个数;i++) //问题1:select后,集合的结构体成员个数是否是 在线的客户端的个数??
{
//由于调用selcet的时候,参数设置为只读套接字,所以只能接受数据
char buf[2000];
::ZeroMemory(buf,sizeof(buf);
int nRet=revc(套接字集合[ i],buf,sizeof(buf));
问题2:select后,说明剩下的套接字只有连接套接字和发送数据的客户端,其他套接字类型是没有的
在这里如何区别是哪一种套接字?
为什么有这个疑问,我想在这里接受数据,然后对数据解包,同时把 接受的套接字 和 数据包的某些内容组成一个
对象,放到map中管理.
}
}
return 0;
}
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;
}
}