在客户端中,一次通信(注:一次通信,指的是从创建->连接->发包->关闭过程)都没问题,问题出在,现在关闭SOCKET,程序不退出,继续创建SOCKET->连接服务器->发送数据,连接、发送均成功,可奇怪的是在recv()时竟然返回0(server端已关闭socket,那现在已经创建好的SOCKET算什么呢??)。  
 
程序主要实现(阻塞,后来改非阻塞也一样):  
在连接成功后,创建带有recv()实现的接收线程,监听网络接收,通信后来我是知道server端已经closesocket()的,此时client也closesocket()响应,退出(安全退出)接收线程。  
 
问题提出:为什么第二次通信行不通呢?我在知道server端已经关闭时就已经关掉socket,并且退出接收线程的。望高手指点,分数可以再加,不是问题,  
郁闷好了几天…………………………  
 
e-mail:  [email protected]  

解决方案 »

  1.   

    同情楼主。
    看看closesocket的返回值吧。
      

  2.   

    to ISunwu(刀口蒙特) 
    检查了,返回0,无错。
    已经知道server端已经关闭了的。
      

  3.   

    这个问题我也遇到过!第一次断开以后服务端的要重新生成对象.
    myCsocket::Onclose()
    {
      m_ServerSocket.close();
      m_ServerSocket.create(端口);
       ...(创建过程)...
    }
      

  4.   

    to  ISunwu(刀口蒙特) 
    我都试过了,一个样阿,
    大哥,help me……
      

  5.   

    to madhappy(545454)
    server端应该已经做到这点了吧,
    server端监听的SOCKET对已被接受的SOCKET才创建吧。
    好像不会无缘无故在关闭一个socket后去创建,这样好像不太合理吧。各位路过的朋友,请发表下高见。要求加分,没问题,
    决不含糊阿钱乃身外物阿,有点扯开了,呵呵
      

  6.   

    ok.有点长了代码,贴主要的吧……//connect
    //主要步骤:
    //WSAStartup() -> Create Socket -> Connect to server -> Create recv thread
    BOOL CClientSocket::Connect(const char* szIPAddr,unsigned short nPort)
    {
    if (szIPAddr == NULL || nPort < 1024) return FALSE; WORD wVersion = MAKEWORD(0x02,0x00);
             // WSAStartup()..
    if (!StartUp(wVersion)) return FALSE;

    if (m_hSocket != INVALID_SOCKET)
    {
    Close ();
    }
    m_hSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
    if (INVALID_SOCKET == m_hSocket) return FALSE;

    SOCKADDR_IN sockAddr;
    DWORD dwIP;
    dwIP = inet_addr(szIPAddr);
    if (dwIP == INADDR_NONE) return FALSE;
    sockAddr.sin_family = AF_INET;
    sockAddr.sin_port = htons(nPort);
    sockAddr.sin_addr.S_un.S_addr = dwIP;

    Sleep(500);
    int nConnect = connect(m_hSocket,(SOCKADDR *)&sockAddr,sizeof(sockAddr));
    if (nConnect == SOCKET_ERROR)
    {
                 DWORD dwErrorCode = GetLastError ();
    if (WSAEWOULDBLOCK != dwErrorCode)
    {
    TRACE(_T("Connect() Socket error: %d..\n"),dwErrorCode);
    //WSAEADDRINUSE
    if (WSAEISCONN == dwErrorCode)
    {
    TRACE(_T("connect(): Socket have connected..\n"));
    // close socket and WSACleanup()
    // Close ();
    // SetLastError(0);
    // continue;
    }
    else if (WSAENOTSOCK == dwErrorCode)
    {
    TRACE(_T("connect(): Not Socket..\n"));
    }
    return FALSE;
    }
    else // WSAEWOULDBLOCK is ignored
    {
    SetLastError(0);
    }
    }
    m_bConnected = TRUE; // connect server successfully
             if (m_hRecvThread != NULL)  // terminate the old Recv thread 
    {
    TerminateThread (m_hRecvThread,0);
    CloseHandle (m_hRecvThread);
    m_hRecvThread = NULL;
    }
    m_hRecvThread = CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE)RecvThread, (LPVOID)this, 0, &m_dwRecvID);
    ASSERT(m_hRecvThread != NULL);
    TRACE(_T("Create Recv Thread,ID: 0x%x\n"),m_dwRecvID);
    return TRUE;
    }// 关闭Socket连接 and WSACleanup()
    BOOL CClientSocket::Close ()
    {
    if (INVALID_SOCKET != m_hSocket)
    {
    // shutdown(m_hSocket,2);
    int iClose = closesocket(m_hSocket);
    if (iClose == SOCKET_ERROR)
    {
    TRACE(_T("closesocket() socket error: %d..\n"),GetLastError ());
    }
    if (WSACleanup () == SOCKET_ERROR)
    {
    TRACE(_T("WSACleanup () socket error: %d..\n"),GetLastError ());
    }
    }
    m_hSocket = INVALID_SOCKET;
    m_bConnected = FALSE;
    return TRUE;
    }
      

  7.   

    // 接收线程实现
    // 接收线程
    DWORD WINAPI CClientSocket::RecvThread(LPVOID lParam)
    {
    if (lParam == NULL) return 1;
    CClientSocket* pClientSock = (CClientSocket*)lParam;

    fd_set fdRead;
    struct timeval tmvTimeout={0L,100L}; while (TRUE)
    {
    // Always clear the read set before calling select()
    FD_ZERO(&fdRead);// EnterCriticalSection (&pClientSock->m_csSynch);
    // add SOCKET m_hSocket to the read set
    FD_SET(pClientSock->m_hSocket,&fdRead); int ret = select(0,&fdRead,NULL,NULL,&tmvTimeout);
                      if (ret == SOCKET_ERROR)
    {
    // Error condition
    TRACE(_T("Select() Socket error: %d..\n"),GetLastError ());
    continue;
    }
    else if (ret > 0)
    {
                                if (FD_ISSET(pClientSock->m_hSocket,&fdRead))
                                {
                                     // read data
                                     nRecv = recv (pClientSock->m_hSocket, chRecv, sizeof(chRecv), 0); // Block here
                                     if (nRecv == SOCKET_ERROR)
         {
                                         // Socket recv error
                                         TRACE(_T("Recv socket error: %d..\n"),GetLastError());
                                     }
                                     else if (nRecv == 0)  // remote socket close
                                     {
                                         TRACE(_T("remote socket closed..\n"));
                                         // close socket and WSACleanup()
    pClientSock->m_bConnected = FALSE;
    pClientSock->Close ();
    TRACE(_T("close client socket..\n"));
                                         // free thread handle
                                         CloseHandle (pClientSock->m_hRecvThread);
    pClientSock->m_hRecvThread = NULL;
                                         break;                                     
                                     }
                                     
                                     // read socket data to buf and to deal with it
                                     TRACE(_T("Recv %x bytes..\n"),nRecv); 
                   //...
                                } 
                       }
             }
             TRACE(_T("Recv thread exit with 0..\n"));
             return 0;
    }相关的程序框架大致如上,希望能得到帮助……
    附:
    class CClientSocket
    {
       public:
            //..
       protected:
           SOCKET m_hSocket;
           //..
    };

      

  8.   

    已经搞定。
    faint,原来是应用层上的失误,这个程序本身是没问题的。呵呵 :)
    一个很关键的量没设置好,而这个恰巧很容易被忽略。
    太累了,折腾了两天……
    可以休息一下了.
    散分了……