2009-12-02 2 views
1

Cette fonction est appelée pour servir chaque client dans un nouveau thread. dans la fonction consommer, ces archives sont lues et écrites mais la fonction retourne avant que le client finisse de lire toute la réponse afin que le socket soit hors de portée et fermé, créant une exception dans le client. Je suppose que n'importe quelle écriture sur le CArchive devrait bloquer jusqu'à ce qu'elle soit lue du côté du client. Est-ce que je fais une mauvaise supposition ici? Le code fonctionne bien si j'ajoute un délai avant de sortir de la portée (essayez) ce qui n'est pas un bon moyen, je me demande s'il y a un moyen de bloquer jusqu'à ce que toutes les données soient transférées?CSocket ne bloque pas sur l'envoi

Merci

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; 
} 

Répondre

1

J'ai trouvé la solution, afin de fermer la connexion sans perdre aucun échange de données, vous devriez essentiellement utiliser l'option SO_LINGER, c'est une très longue histoire, vous pouvez voir les détails dans this article

mais l'étrange la partie est, MSDN semble très inexact quand il vient à l'arrêt, dans mon expérience, les options de LINGER n'ont eu aucun effet sur l'arrêt et si vous appelez l'arrêt avant la fermeture alors la fermeture suivante ne bloquera plus!

enfin, voici le nouveau code

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

Je n'ai pas une idée exacte sur le problème ici. Quoi qu'il en soit s'il vous plaît essayez ce qui suit, il peut résoudre votre problème. Ne pas autoriser clientSocket à être détruit. Pour cela, vous pouvez soit le créer dynamiquement ou dans une portée globale comme suit.

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

2. CSocket clientSocket; // Global scope 

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

Il est un serveur très occupé. Je ne peux pas me permettre de garder les prises longtemps pour que votre solution ne soit pas applicable dans mon cas. – Mehran

Questions connexes