2

ソケットプログラミングを含むアプリケーションに取り組んでいます。サーバーが何らかの理由で閉じられたりクラッシュした場合に備えて、このアプリケーションにリセット機能を実装しようとしています。リセットするには、サーバーを手動で再起動した後、クライアントとサーバー間の通信を再確立する必要があります。これで、クライアントからサーバーに要求を送信し、サーバーが処理してクライアントに応答を送信できるようになりました。Send()サーバー側の関数は成功して返されますがWSAWaitForMultipleEvents()、クライアント側の関数はWSA_TIME_OUT毎回返されます。

SO_REUSEADDRリセット時に真の値でクライアント側でソケットを再起動します。私はネットワークプログラミングに非常に慣れていないので、なぜこれが起こっているのか理解できません。

これがクライアント側の私のコードです。少しめちゃくちゃなので、ご容赦ください

void 
SocketListner::run()
{
    // std::cout << "Thread ID of SocketListener : " << QThread::currentThreadId() << "\n";
    if(_isFrameGrabber)
    {
        _listenForFrames();
    }
     else
    {
        _listenForRequests();
    }
}

void
SocketListner::_listenForRequests()
{
    DWORD eventVal;
    unsigned int eventSock;
    WSANETWORKEVENTS networkEvents;
    std::stringstream ss;

    int bufferLength = 500;
    char * msg = new char[bufferLength];
    std::string Msg = "";
    int retCode;
    int diff;

    while(!_done)
    {
        // Giving it one second less than the condition wait time
   //     OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_destructorMutex);
        if((eventVal=WSAWaitForMultipleEvents(_eventCnt, _socketEvents, false, 3000, false)) == WSA_WAIT_FAILED)
        {
            ss.str("");
            ss << "WSAWaitForMultipleEvents() failed with error : " << WSAGetLastError();
            LOG_ERROR(ss.str());
            emit socketErrorSignal(eventVal);
            break;
        }
        else if(eventVal == WSA_WAIT_TIMEOUT)
        {
            //OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
            if(_done)
            {
                WSACloseEvent(_socketEvents[0]);
                if(_eventCnt==2)
                    WSACloseEvent(_socketEvents[1]);
                break;
            }
            continue;
        }

        if( (diff=(eventVal - WSA_WAIT_EVENT_0)) == 0 )
            eventSock = s_sock;
        else if(diff == 1)
            eventSock = c_sock;
        else 
            continue;

        if((WSAEnumNetworkEvents(eventSock, _socketEvents[eventVal - WSA_WAIT_EVENT_0], &networkEvents)) == SOCKET_ERROR)
        {
            ss.str("");
            ss << "WSAEnumNetworkEvents() failed with error : " << WSAGetLastError();
            LOG_ERROR(ss.str());
            // break;
        }

        if (networkEvents.lNetworkEvents & FD_ACCEPT)
        {
            if (networkEvents.iErrorCode[FD_ACCEPT_BIT] != 0)
            {
                ss.str("");
                ss << "FD_ACCEPT failed with error : " << networkEvents.iErrorCode[FD_ACCEPT_BIT];
                LOG_ERROR(ss.str());
                break;
            }

            if ((c_sock = accept(eventSock, NULL, NULL)) == INVALID_SOCKET)
            {
                ss.str("");
                ss << "accept() failed with error : " << WSAGetLastError();
                LOG_ERROR(ss.str());
                break;
            }

            if ((_socketEvents[_eventCnt] = WSACreateEvent()) == WSA_INVALID_EVENT)
            {
                std::stringstream ss;
                ss << "WSACreateEvent() failed with error : " << WSAGetLastError();
                LOG_ERROR(ss.str());
                break;
            }

            if( WSAEventSelect(c_sock, _socketEvents[_eventCnt], FD_READ | FD_CLOSE) == SOCKET_ERROR)
            {
                ss.str("");
                ss << "WSAEventSelect() failed with error : " << WSAGetLastError();
                LOG_ERROR(ss.str());
                break;
            }

            ++_eventCnt;
        }

        if(networkEvents.lNetworkEvents & FD_READ)
        {
            if (networkEvents.lNetworkEvents & FD_READ && networkEvents.iErrorCode[FD_READ_BIT] != 0)
            {
                ss.str("");
                ss << "FD_READ failed with error : " << networkEvents.iErrorCode[FD_READ_BIT];
                LOG_ERROR(ss.str());
            }

            if((retCode = recv(eventSock, msg, bufferLength, 0)) > 0)
            {
                int place = 0;
                while(place < retCode)  
                {
                    if(msg[place] == '\n' && Msg.length() != 0)
                    {
                        OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
                        //Naresh: Replacing std::vector by std::queue
                        _requests.push(Msg);
                        Msg = "";
                    }
                    else
                    {
                        if(msg[place] != '\0')
                            Msg.push_back(msg[place]);
                    }
                    ++place;
                }
            }
            //Abhishek: Testing Complete else block
            else if(retCode == 0 || WSAGetLastError() == WSAECONNRESET)
            {
                //Abhishek
                shutdown(c_sock, SD_BOTH);
                shutdown(s_sock, SD_BOTH);
                closesocket(c_sock);
                closesocket(s_sock);
                int error = WSAGetLastError();

                if(!_initialize())
                {
                    _done = true;
                    return;
                }
            }
            else if(retCode == SOCKET_ERROR)
            {
                bool stopListening=false;
                int errorCode = WSAGetLastError();
                _processSocketError(errorCode, stopListening);          

                if(stopListening)
                {
                    LOG_WARNING("Connection with the partner lost.");
                    emit socketErrorSignal(errorCode);
                    break;
                }
            }
        }

        if(networkEvents.lNetworkEvents & FD_CLOSE)
        {
            if (networkEvents.iErrorCode[FD_CLOSE_BIT] != 0)
            {
                ss.str("");
                ss << "FD_CLOSE failed with error : " <<  networkEvents.iErrorCode[FD_CLOSE_BIT];
                LOG_ERROR(ss.str());
                emit socketErrorSignal(networkEvents.iErrorCode[FD_CLOSE_BIT]);
            }
            else if(!_stopped)
            {
                LOG_ERROR("Lost Connection with Wall.");
                emit socketErrorSignal(networkEvents.iErrorCode[FD_CLOSE_BIT]);
            }

            closesocket(eventSock);
            break;
        }
        //Sleep(100);
    } //While

    delete[] msg;
    msg = NULL;

    // If any failure occurs make the _bDone  variable to true, as thread is no longer running
    _cleanUpCondition.signal();
}

ここに_initialize関数があります

bool 
SocketListner::_initialize()
{
    if(_IP.length() <= 0)
    {
        LOG_ERROR("Host IP Address : " + _IP + " is invalid.");
        return false;
    }

    //Naresh: replacing vector by queue
    while(!_requests.empty())
    {
        _requests.pop();
    }

    WSADATA wsaData;

    if(WSAStartup(0x101,&wsaData) != 0)
    {
        LOG_ERROR("Failed WSAStartUp() call.");
        return false;
    }

    sockaddr_in SockAddr;

    SockAddr.sin_family = AF_INET;
    SockAddr.sin_port = htons(_port);
    SockAddr.sin_addr.s_addr =  inet_addr(_IP.c_str());

    s_sock = socket(AF_INET,SOCK_STREAM,0);
    //Abhishek:BugFix for reset enable address reuse else bind() will fail
    bool addrReuse = true;
    setsockopt(s_sock, SOL_SOCKET, SO_REUSEADDR, (const char*) &addrReuse, sizeof(BOOL));

    if(!_isFrameGrabber)
    {
        if ((_socketEvents[_eventCnt] = WSACreateEvent()) == WSA_INVALID_EVENT)
        {
            std::stringstream ss;
            ss << "WSACreateEvent() failed with error : " << WSAGetLastError();
            LOG_ERROR(ss.str());
            return false;
        }

        if(WSAEventSelect(s_sock, _socketEvents[_eventCnt], FD_ACCEPT | FD_CLOSE)== SOCKET_ERROR)
        {
            std::stringstream ss;
            ss << "WSAEventSelect() failed with error : " << WSAGetLastError();
            LOG_ERROR(ss.str());
            return false;
        }
        ++_eventCnt;
    }

    if(s_sock == INVALID_SOCKET)
        return false;

    int errorCode = bind(s_sock,(sockaddr*)&SockAddr,sizeof(SockAddr));

    if(errorCode == SOCKET_ERROR)
    {
        bool stopListening = false;

        _processSocketError(WSAGetLastError(), stopListening);
        return false;
    }

    if(listen(s_sock,10)!=0)
    {
        return false;
    }

    return true;
}
4

2 に答える 2

0

ピアが停止した場合、必ずしもイベントが発生するとは限りません。TCP で切断された接続を検出する唯一の信頼できる方法は、それに書き込むことです。切断された接続への最初の書き込みはおそらく成功しますが、その後の書き込みは失敗します。

于 2012-07-11T23:32:00.907 に答える
0

私の問題の解決策を見つけました。現在、アプリケーションのリセット時にすべてのスレッドとソケットを再起動しています。その後、新しいソケットに接続できなかったため、サーバーが送信できなかったことがわかりました。sendData()関数でクライアント ソケットに接続しようとするための無限ループを配置しました。それは私のためにトリックをしました。

于 2012-07-12T09:34:05.860 に答える