解决方案 »
- 快圣诞了,借国外的节日祝大家平安!顺便散分!另外提醒大家及时结贴!
- 我在设计窗体时,右下角显示窗体大小比实际窗体分辨率小很多,有什么办法在设计期就画出一个800*600分辨率的窗体来?
- 要求屏保后需要密码保护,此时需要用软键盘来输入密码,可否实现
- access读入时出现错误
- 如何在初始化的时候让菜单处于CHECK状态?
- &&请问大家知道免费的电脑图书的网址吗?&&
- 诚聘·思易电子(杭州)·开发人员
- 关于编译与连接。。它们有什么不一样。。
- 指针与文件的问题
- vc
- vs2010出现“无法解析的外部符号 __imp___vsnprintf"
- widnows下是每个线程都有一个栈,还是共享进程的栈?我倾向于前者
就从我对代码的理解角度分析下吧
问题1:
如果你的只读套接字set只被AcceptThread线程中的FD_SET(newAddrin,&newSocket)访问
且你的在线客户端都是通过这个FD_SET来添加的话,那集合的结构体成员个数是在线的客户端的个数
问题2:
这个得等专家来解释了,不敢乱讲
不懂原理直接干活会头疼的select都不做返回直判断,你怎么判断套接字到底可不可用。问题点太多,很多知识需要补。
http://blog.csdn.net/yanheifeng715000/article/details/6592447
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}
for ()
{
if (FD_ISSET(socket, &只读集合))
{
//有数据
}
else
{
//没有数据
}
}
真的假的啊, 我以为它的作用是去掉断线的socket
照这样的话
加入服务器连接10个客户端,他们都没掉线就一个客户端和服务器通信,其他一依然连接,那9个客户端会被select去掉吗?
所以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;
}
}