fd_set fdSocket;
FD_ZERO(&fdSocket);
FD_SET(sListen,&fdSocket);
while (true)
{
fd_set fdRead=fdSocket;
int nRet=select(0,&fdRead,NULL,NULL,NULL);
if (nRet>0)
{
for (int i=0;i<(int)fdSocket.fd_count;i++)
{
if (FD_ISSET(fdSocket.fd_array[i],&fdRead))
{
char szText[256];
int nRecv=recv(fdSocket.fd_array[i],szText,256,0);
if (nRecv>0)
{
szText[nRecv]='\0';
cout<<"接收到数据:"<<szText<<endl;
}
else
{
closesocket(fdSocket.fd_array[i]);
FD_CLR(fdSocket.fd_array[i],&fdSocket);
}
}
}
}
else
{
cout<<"Select执行失败!\n";
break;
}
}
这段代码在for (int i=0;i<(int)fdSocket.fd_count;i++)这个for循环体内,又会调用FD_CLR去改变fdSocket,这样是不是有问题呀,我觉得这样有可能会跳过一些套接字。举个例子,i = 0时,fdSocket里面有1,2,3,4,5。
如果他删掉了1,再次进入循环时fdSocket.fd_count变成4了,而i变成1了,fdSocket里剩下2,3,4,5。
这样,岂不就跳过了2,直接判断3了???请大家指教,谢谢!
其实在循环内部不用FD_CLR,应该在for (int i=0;i<(int)fdSocket.fd_count;i++)循环结束后一次性FD_ZERO,然后还得再一遍FD_SET。
那请问如何在fdSocket中保存住有效的套接字呢?不用FD_CLR的话,下次循环fdSocket里面就会有失效的套接字了...
谢谢,我这个socket是长连接,select不限时的.
int nRet=select(0,&fdRead,NULL,NULL,NULL);
if (nRet>0)
{
for (int i=0;i<(int)fdRead.fd_count;i++)
{ char szText[256];
int nRecv=recv(fdRead.fd_array[i],szText,256,0);
if (nRecv>0)
{
szText[nRecv]='\0';
cout<<"接收到数据:"<<szText<<endl;
}
else
{
FD_CLR(fdRead.fd_array[i],&fdSocket);
closesocket(fdRead.fd_array[i]);
}
}
}
下次循环之前也就是 for (int i=0;i<(int)fdSocket.fd_count;i++)循环结束后FD_ZERO一下,再FD_SET一下。
兄弟,这个closesocket和fd_clr的先后顺序应该没问题的吧。
支持!收不到就表示该SOCKET已经退出了!
fd_set fdSocket;
FD_ZERO(&fdSocket);
FD_SET(&fdSocket, sListen);while(TRUE)
{
fd_set fdRead = fdSocket;
int nRet = select(0, &fdRead, NULL, NULL, NULL);
if(nRet > 0)
{
for(int i=0; i<(int)fd_Socket.fd_count; i++)
{
if(FD_ISSET(fdSocket.fd_array[i], &fdRead)
{
if(sListen == fdSocket.fd_array[i])
{
if(fdSocket.fd_count < FD_SETSIZE)
{
SOCKADDR_IN remote;
int len = sizeof(remote);
SOCKET sNew = accept(sListen, (LPSOCKADDR)&remote, &len);
FD_SET(sNew, &fdSocket);
}
else
{
// Too much client
continue;
}
}
else
{
char szText[256] = {0};
int nRecv = recv(fdSocket.fd_array[i], sztext, 256, 0);
if(nRecv > 0)
{
// print recv data
}
else
{
closesocket(fdSocket.fd_array[i]);
FD_CLR(fdSocket.fd_array[i], &fdSocket);
}
}
}
}
}
else
{
// select errror;
break;
}
}
不好意思,我怎么还是觉得这样写会有bug,就想我在帖子描述中提问的那样...
vector<int> bb;
bb.push_back(0);
bb.push_back(1);
bb.push_back(2);
bb.push_back(3);
bb.push_back(4); vector<int>::const_iterator begin; for (begin = bb.begin(); begin != bb.end(); ++begin)
{
cout << *begin << endl; if (*begin == 2)
begin = bb.erase(begin);
}
就像这段代码一样,只能输出0,1,2,4,而3被跳过去了...
select函数的作用要明白,函数返回后fdRead里就全部是可读的套接字了(不可读的会被清除出数组)
所以for轮询fdRead,接收下数据就可以,不需要轮询fdSocket并用FD_ISSET这个判断了的
套接字关闭后也是可读的,这时读到返回是0罢了,这时先从fdSocket清除这个socket值然后再closesocket就可以了,下次再select,从新把fdSocket赋值给fdRead即可。
呃,兄弟,我明白了,有一个地方我之前看走眼了。
可否指教一下,11楼的代码是否像我分析的那样,有bug,因为他for循环直接用fdSocket判断的,而不是像你的代码,用fdRead判断的,这样可能会漏泄某些套接字吧。
FD_ZERO(&fdSocket);
FD_SET(&fdSocket, sListen);while(TRUE)
{
fd_set fdRead = fdSocket;
int nRet = select(0, &fdRead, NULL, NULL, NULL);
if(nRet > 0)
{
for(int i=0; i<(int)fd_Socket.fd_count; i++)
{
if(FD_ISSET(fdSocket.fd_array[i], &fdRead)
{
char szText[256] = {0};
int nRecv = recv(fdSocket.fd_array[i], sztext, 256, 0);
if(nRecv > 0)
{
// print recv data
}
else
{
closesocket(fdSocket.fd_array[i]);
FD_CLR(fdSocket.fd_array[i], &fdSocket);
}
}
}
}
我还是觉得有问题啊,假如fd_Socket里有socket1,2,3,4,5。
而select一次后,fdRead里剩下socket1,2,3。
第一次循环的时候,i = 0,recv socket1的时候,得到的结果是0,那么socket1就从fd_Socket里面去掉了。
第二次循环的时候,i = 1,fd_Socket里面剩下socket2,3,4,5。这样fdSocket.fd_array[i]就变成socket3了,那么socket2不就被跳过了吗?求解释...
int nRet = select(0, &fdRead, NULL, NULL, NULL);
这2个代码,为什么这边需要进行个赋值呢。把fdSocket 给了fdRead,然后select 的是fdread呢?
select 后,fdread里面永远是可以使用的,那些不能使用的就不会在fdread里面呢
而且在select结束后和再一次select前 fdread的里面的是没有变化的,永远是上一次select的结果。不知道是否能否符合你的意思
因为在select内部还可能调用FD_SET向fdSocket里面新增套接字。
说的没错,正是因为这个原因,所以我认为有Bug的代码一次For循环中如果调用了FD_CLR,那么会跳过下一个套接字,这也是我对11楼代码及楼顶代码的疑问所在。我想,由于套了while循环,所以它可以正常工作,因为被跳过的套接字下一次进入while循环的时候还是会被处理。但单从一次for循环的开始到结束来看,我认为那一小段代码的逻辑就是有问题的。不知道理解的对不对,求鉴定!
vector<int> bb;
bb.push_back(0);
bb.push_back(1);
bb.push_back(2);
bb.push_back(3);
bb.push_back(4); vector<int>::const_iterator begin= bb.begin(); for (; begin != bb.end();)
{
cout << *begin << endl; if (*begin == 2)
begin = bb.erase(begin);
else
++begin;
}
{
fd_set fdSocket;
FD_ZERO(&fdSocket);
FD_SET(1, &fdSocket);
FD_SET(2, &fdSocket);
FD_SET(3, &fdSocket);
FD_SET(4, &fdSocket);
for (int i = 0; i < (int)fdSocket.fd_count;)
{
printf("%d ", fdSocket.fd_array[i]);
if (fdSocket.fd_array[i] == 2)
FD_CLR(fdSocket.fd_array[i], &fdSocket);
else
i++;
}
}