2011-03-28 7 views
2

개인 학습 목적으로 MUD 서버를 쓰고 있습니다. 행복하게 소켓 클래스를 몇 가지 클래스로 마무리하고 모든 것이 올바르게 작동하는 것처럼 보입니다. ; 서버는 연결을 수신하고 받아들이고 현재 클라이언트에서 텍스트를 가져 와서 바로 보냅니다.accept()에 대한 불량 호출 처리에 대한 염려

문제는 WSAEWOULDBLOCK 또는 유효한 소켓 이외의 것을 반환하는 accept() 호출과 관련하여 확실하지 않습니다. 새 소켓을 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이라고 가정합니다. 다른 것을하면 나중에 실제 소프트웨어에서 실제 버그가 생길 것입니다 (나를 믿어 의심치 않습니다 : 유효하지 않은 소켓 fd로 0을 사용하는 디버깅 코드에서 경험하고 있습니다).

그 외, 나는 단지 예외를 제기한다고 말하고 싶습니다. accept은 자원이 부족한 경우가 아니면 예외가 아니며 오류가 발생해야합니다. C++은 그런 것들을 처리하는 메커니즘을 가지고 있으며, 그것은 예외입니다.

BTW : delete this은 항상 매우 나쁜 생각입니다. 코드 중간에 종료하면 디버깅하기가 어려울 수 있습니다 (대신 예외가 발생 함). 필요하다면 발신자가 종료하도록 할 수 있습니다. accept 소켓을 받아들이려는 경우 select을 사용하여 받아 들일 수있는 것이 있는지 여부를 알 수 있습니다. 특수 케이스 처리를 해당 기능에서만 선택하여 이동할 수 있습니다. 좀 더 나아가 전문화 된 옵서버 패턴 (예 : my podcast)을 구현하여 네트워킹 코드뿐만 아니라 디자인 패턴도 연습 할 수 있습니다. 이는 또한 코드를 더 이식성있게 만들고 나중에 다시 사용할 수있게 도와줍니다.

HTH

+0

정보를 제공해 주셔서 감사합니다. –

0

오류를 반환하고 호출 코드가 적절하게 처리하도록합니다.

+0

전체적인 요점은 무엇인지 적절한 방법으로 처리 할 수 ​​있을지 모르겠습니다. 이것은 다른 곳에서 사용하기 위해 나가기를 계획하고있는 것이 아닙니다. 적어도 지금 당장은 사용하지 않기 때문에 어떻게 처리해야하는지에 대한 아이디어를 얻으 려합니다. –

0

동의에서 가능한 다른 오류 중 일부는 메모리, 연결의 수, 소모 낮은 점이다 등 등

아마도이되지 않거나 잊어 연결을 폐쇄하거나 포기에 의해 처리 될 수 있습니다 및 예외를 던지기.

+0

나는 현재 소켓에있는 recv()로부터 SOCKET_ERROR가 반환 될 때 그 소켓을 다른 목록에 스플 라이스 할 수있는 코드를 설정했다. 명부. –