当send()成功时,WSAWaitForMultipleEvents返回超时

时间:2012-07-06 21:54:32

标签: sockets visual-c++ networking network-programming winsock

我正在开发一个涉及套接字编程的应用程序。我试图在此应用程序中实现重置功能,以防服务器因任何原因关闭或崩溃。为了重置,我需要在手动重启服务器后重新建立客户端和服务器之间的通信。现在我能够从客户端向服务器发送请求,服务器将处理并向客户端发送回复。服务器端的Send()函数返回成功,但客户端的WSAWaitForMultipleEvents()函数每次都返回WSA_TIME_OUT

我在客户端重新启动套接字,重置时{true}值为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;
}

2 个答案:

答案 0 :(得分:0)

如果同伴死亡,则根本不会发生任何事件。检测TCP中断连接的唯一可靠方法是写入它。对断开的连接的第一次写入可能会成功,但后一次写入将失败。

答案 1 :(得分:0)

我找到了解决问题的方法。现在我在我的应用程序中重启时重新启动所有线程和套接字。之后我发现服务器无法发送,因为它无法连接新的套接字。我在我的sendData()函数中设置了一个无限循环来尝试连接到客户端套接字。这对我有用。