代码之家  ›  专栏  ›  技术社区  ›  Mehran ShankarSangoli

CSocket在发送时未阻塞

  •  1
  • Mehran ShankarSangoli  · 技术社区  · 15 年前

    调用此函数为新线程中的每个客户机提供服务。在consume函数中,这些归档文件被读取和写入,但函数在客户端完成读取所有响应之前返回,因此套接字超出范围并关闭,从而在客户端中创建异常。我假设CArchive上的任何写操作都应该阻塞,直到客户端读取为止。我在这里做了一个错误的假设吗?

    谢谢

    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;
    }
    
    2 回复  |  直到 15 年前
        1
  •  1
  •   Mehran ShankarSangoli    15 年前

    我找到了解决方案,为了在不丢失任何未交换数据的情况下关闭连接,您基本上应该使用SO_LINGER选项,这是一个非常长的故事,您可以在中看到详细信息 this article

    最后,这里是新代码

       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;
    }
    
        2
  •  0
  •   Vadakkumpadath    15 年前

    不允许 clientSocket

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