2009-12-02 41 views
1

調用此函數以在新線程中爲每個客戶端提供服務。在消費函數中,這些檔案被讀取和寫入,但函數在客戶端完成讀取所有響應之前返回,以便套接字超出範圍並關閉,從而在客戶端中創建異常。我假設在CArchive上的任何寫入都應該阻塞,直到在客戶端讀取它爲止。我在這裏做出錯誤的假設嗎? 如果我在超出範圍(嘗試)之前添加延遲(這不是一種好方法),代碼工作正常,我不知道在阻止所有數據傳輸之前是否有任何方法阻止?CSocket在發送時不會阻塞

感謝

UINT CNetServer::serveClient(LPVOID p) 
{ 
    serveClientParams* params = reinterpret_cast<serveClientParams*>(p); 
    try 
     { 
      AfxSocketInit(); 
      CSocket clientSocket; 
      clientSocket.Attach(params->ClientSocket); 
      CSocketFile file(&clientSocket); 
      CArchive arIn (&file, CArchive::load); 
      CArchive arOut(&file, CArchive::store); 
     params->ServerInstance->Consumer.Consume(arIn, arOut); 

      arOut.Flush(); 
      file.Flush(); 
        //SleepEx(1000,true); works fine is I wait till the data is sent. 
     } 
     catch(int ex) 
     { 
      CMisc::LogWriteWarning(ex, GetLastError(), "Listen Loop Communication"); 
     } 
     catch(CException* ex) 
     { 
      char buffer[1024]; 
      ex->GetErrorMessage(buffer, sizeof(buffer)); 
      CMisc::LogWriteError(buffer, SOCKET_COMUNICATION_FAILED); 
     } 
     catch(...) 
     { 
      CMisc::LogWriteWarning(0, GetLastError(), "abnormal communication termination."); 
     } 
     delete params; 
     return 0; 
} 

回答

1

我找到了解決辦法,爲了關閉連接而不會丟失任何沒有交換的數據,你應該基本使用SO_LINGER選項,這是一個很長的故事,你可以看到在this article

但奇怪的細節部分是,MSDN在關機時看起來非常不準確,根據我的經驗,LINGER選項對關機沒有影響,如果您在關閉之前調用shutdown,那麼隨後的關閉將不會阻止!

最後,這裏是新代碼

UINT CNetServer::serveClient(LPVOID p) 
{ 
    serveClientParams* params = reinterpret_cast<serveClientParams*>(p); 
    try 
     { 
      AfxSocketInit(); 
      CSocket clientSocket; 
      clientSocket.Attach(params->ClientSocket); 

      struct linger linger; 
      linger.l_linger = 9; 
      linger.l_onoff = 128; 
      int fls = 0; 

      int i = clientSocket.SetSockOpt(SO_LINGER, &linger, sizeof(linger)); 
      i = clientSocket.SetSockOpt(SO_DONTLINGER, &fls, sizeof(fls)); 

      CSocketFile file(&clientSocket); 
      CArchive arIn (&file, CArchive::load); 
      CArchive arOut(&file, CArchive::store); 
      params->ServerInstance->Consumer.Consume(arIn, arOut); 

      arOut.Flush(); 
      //BOOL b = clientSocket.ShutDown(SD_BOTH); 
     } 
     catch(int ex) 
     { 
      CMisc::LogWriteWarning(ex, GetLastError(), "Listen Loop Communication"); 
     } 
     catch(CException* ex) 
     { 
      char buffer[1024]; 
      ex->GetErrorMessage(buffer, sizeof(buffer)); 
      CMisc::LogWriteError(buffer, SOCKET_COMUNICATION_FAILED); 
     } 
     catch(...) 
     { 
      CMisc::LogWriteWarning(0, GetLastError(), "abnormal communication termination."); 
     } 
     delete params; 
     return 0; 
} 
0

我沒有關於該問題的確切想法在這裏。無論如何請嘗試以下,它可能會解決您的問題。

不允許clientSocket被銷燬。爲此,您可以按照以下方式動態或全局範圍地創建它。

1. UINT CNetServer::serveClient(LPVOID p) 
    { 
     : 
     CSocket* clientSocket = new CSocket; 
     : 
    } 

2. CSocket clientSocket; // Global scope 

    UINT CNetServer::serveClient(LPVOID p) 
    { 
     : 
    } 
+0

這是一個非常繁忙的服務器。我不能長時間保持插座,所以你的解決方案不適用於我的情況。 – Mehran 2009-12-04 15:29:54