2012-07-06 120 views
2

我正在研究涉及套接字編程的應用程序。我試圖在服務器因任何原因關閉或崩潰的情況下在此應用程序中實現重置功能。對於重置,我需要在手動重新啓動服務器之後重新建立客戶端和服務器之間的通信。現在,我可以發送客戶端到服務器的請求,哪個服務器會處理並向客戶端發送回覆。 Send()服務器端功能正在返回成功,但WSAWaitForMultipleEvents()客戶端功能每次都返回WSA_TIME_OUTWSAWaitForMultipleEvents在send()成功時返回超時

我重新啓動我的套接字在客戶端與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; 
} 
+0

如果在套接字上發生錯誤,在大多數情況下它將變得不可用,並且必須打開一個新的套接字。同樣如果你關閉()它。也許你試圖通過這種不可用的套接字發送/接收? – 2012-07-06 22:44:48

+0

請顯示您的實際代碼。您的描述太模糊,無法用來診斷任何內容。你很可能在客戶端使用WSAWaitForMultipleEvents()錯誤的方式。 – 2012-07-07 08:43:14

+0

我添加了一段代碼。將關閉一個套接字並重新初始化它將被視爲打開一個新的套接字? – 2012-07-07 11:24:04

回答

0

如果貴族死後會有不一定是任何事件都沒有。檢測TCP中斷連接的唯一可靠方法是寫入它。第一次寫入斷開的連接可能會成功,但稍後會失敗。

0

我找到了解決我的問題的方法。現在我正在重新啓動應用程序中的所有線程和套接字。之後,我發現服務器無法發送,因爲它無法連接新的套接字。我在我的sendData()函數中放置了一個無限循環以嘗試連接到客戶端套接字。對我來說,這是訣竅。