2011-03-28 70 views
2

我正在编写一个MUD服务器用于个人学习的目的,我愉快地设法将套接字填充到几个类中,并且一切似乎都正常工作;服务器侦听并接受连接,并且当前从客户端获取文本并将其发回。关于处理不好的电话接受()

事情是我不太确定如何调用accept(),它返回WSAEWOULDBLOCK或有效套接字以外的内容。我是否只是将新套接字重置为0并返回,可能是错误消息说有什么不好的事情发生?这就是我现在正在做的事情,如果发生了20次,我会关闭服务器。

void MUDControlSocket::Poll() 
{ 
    // create a new connection here 
    timeval timeout; 

    FD_ZERO(&ReadSet); 
    FD_ZERO(&WriteSet); 
    FD_ZERO(&ExceptionSet); 

    TopSocket = GetSocket(); 
    NewSocket = 0; 
    FD_SET(GetSocket(), &ReadSet); 

    if(SocketList.size() > 0) 
    { 
     for(sockIter iter = SocketList.begin(); iter != SocketList.end(); ++iter) 
     { 
     FD_SET((*iter)->GetSocket(), &ReadSet); 
     FD_SET((*iter)->GetSocket(), &WriteSet); 
     FD_SET((*iter)->GetSocket(), &ExceptionSet); 
     TopSocket = (*iter)->GetSocket(); 
     } 
    } 

    if(select(TopSocket+1, &ReadSet, &WriteSet, &ExceptionSet, &timeout) == SOCKET_ERROR) 
    { 
     cout << "Error on select() call: " << SocketErrorType(WSAGetLastError()) << endl; 

     delete this; 
     exit(EXIT_FAILURE); 
    } 

    // as long as everything is working correctly, this if block should always be entered UNLESS a new connection is accepted 
    if((NewSocket = accept(GetSocket(), NULL, NULL)) == INVALID_SOCKET) 
    { 
     if(WSAGetLastError() == WSAEWOULDBLOCK) // it's not an actual problem. just nothing to connect to yet 
     return; 
     NewSocket = 0; 
     static int count = 0; 
     cout << "Error on accepting new connection: " << SocketErrorType(WSAGetLastError()) << endl; 
     if(++count >= 20) 
     done = true; 
     return; 
    } 

    SocketList.push_back(new MUDSocket(NewSocket)); // only happens if accept DOES NOT return a value of INVALID_SOCKET i.e. a new connection was accepted 
    TopSocket = NewSocket; 
    NewSocket = 0; 
} 

TopSocket和NewSocket的类型是SOCKET,并在文件范围声明。 SocketList是MUDSocket *的std :: list,而MUDControlSocket是作为单例从MUDSocket派生的。

让我知道你是否需要更多的信息,并感谢您的任何帮助。

回答

0

第一:不要将套接字设置为0:这是某些* NIX系统上套接字的有效fd,也是一个不好的习惯。假设唯一无效的套接字fd是-1。做任何事情都会在以后的真实软件中给你带来真正的错误(相信我:我是从调试使用0作为无效套接字fd的代码的经验来讲)。

除此之外,我会说只是引发一个异常:accept应该不会失败,除非你用尽资源,这应该是例外和错误。 C++有处理这种事情的机制,这是例外。

顺便说一句:delete this几乎总是一个非常糟糕的想法,在代码中间退出可能会导致难以调试(取而代之的是抛出异常)并让调用者在需要时退出),而不是试图接受一个带有accept的套接字,你可以使用select来告诉你是否有任何东西可以接受 - 并将特殊情况处理移出该功能以仅在那里选择。你可以进一步实现一个专门的观察​​模式(就像我在大约一个月前在my podcast上做的那样),不仅练习你的网络代码,而且练习你的设计模式。这也有助于使代码更加便于携带,并在以后重新使用。

HTH

+0

感谢您的信息。 – 2011-03-30 18:01:47

0

返回错误并让调用代码适当地处理它。

+0

整点是我不知道什么是适当的方式来处理它。这并不是我计划在其他地方使用的东西,至少现在不是,所以我正试图就如何处理它提出一些想法。 – 2011-03-28 22:51:31

0

一些其他错误,从接受可能是内存不足,连接数耗尽,等等等等

也许它可以通过关闭不使用的或忘记的连接,或者干脆放弃处理并抛出异常。

+0

我目前有一些代码设置,从SOCKET_ERROR从套接字上的recv()返回时,将该错误的套接字拼接到另一个列表中,该列表在某些时候通过调用delete中的所有内容清除掉,然后清空名单。 – 2011-03-28 22:49:27