【问题标题】:WSAWaitForMultipleEvents returns timeout when send() is successful当 send() 成功时,WSAWaitForMultipleEvents 返回超时
【发布时间】:2012-07-06 21:54:31
【问题描述】:

我正在开发一个涉及套接字编程的应用程序。我正在尝试在此应用程序中实现重置功能,以防服务器因任何原因关闭或崩溃。对于重置,我需要在手动重新启动服务器后重新建立客户端和服务器之间的通信。现在我可以将请求从客户端发送到服务器,该服务器将处理并向客户端发送回复。服务器端的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;
}

【问题讨论】:

  • 如果一个套接字发生错误,在大多数情况下它会变得不可用,必须打开一个新的套接字。同样,如果您 shutdown() 它。也许您正试图通过这样一个无法使用的套接字发送/接收?
  • 请出示您的实际代码。您的描述太模糊,无法诊断任何东西。您很可能在客户端以错误的方式使用WSAWaitForMultipleEvents()
  • 我添加了代码。关闭套接字并重新初始化它会被视为打开一个新套接字吗?
  • 没有重新初始化套接字这样的事情。一旦你关闭它,它就死了,你必须创建一个新的。
  • 重新初始化意味着关闭当前套接字并再次调用initialize() 函数。就像重新设置一切。它应该只是创建一个新的套接字。

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


【解决方案1】:

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-24
      • 2011-10-16
      • 1970-01-01
      • 2017-06-05
      • 2021-07-25
      • 1970-01-01
      • 2016-03-08
      • 2012-03-20
      相关资源
      最近更新 更多