我在写一个端口转发程序,接受客户端连接后把数据转发到web服务器,是多线程的程序,我用网上的 聊天程序在本机上测试,好比开了10个客户端,1个服务器,这时候能正常通信,但关闭一个客户端的时 候,别的客户端却显示有服务器退出的消息,不该影响别的客户端的啊,而且有的发消息根本发不了了, 客户端列表里有内容,但发不到服务器端,一个客户端关闭时我设置跳出了该线程函数的while循环,这 时候关闭了两个socket closesocket,而如果把这两句注释了的话就没有问题。   我的理解是关闭一个客户端时只是把这个客户端通信用的两个socket关闭了,不会影响其它的啊 请大 家帮忙解决下

解决方案 »

  1.   

    DWORD WINAPI WorkerThread::TransmitData(LPVOID lParam)//在两个SOCKET中进行数据转发
    {
     SOCKINFO socks = *((SOCKINFO*)lParam);
     SOCKET ClientSock = socks.ClientSock;
     SOCKET ServerSock = socks.ServerSock;
     char RecvBuf[MAXBUFSIZE] = {0};
     fd_set Fd_Read;
     int ret, nRecv;
     //struct  timeval timeout = {5,1000};    while(1)
     {

     FD_ZERO(&Fd_Read);
     FD_SET(ClientSock, &Fd_Read);
     FD_SET(ServerSock, &Fd_Read);
     ret = select(FD_SETSIZE, &Fd_Read, NULL, NULL, NULL);
     //int b=sizeof(unsigned int);
     //int a=WSAGetLastError(); 10038 
     if(ret <= 0)   //WSAENETDOWN WSAEINVAL WSAEINTR WSAEINPROGRESS WSAENOTSOCK
        goto error;
     if(FD_ISSET(ClientSock, &Fd_Read))
     {
     nRecv = recv(ClientSock, RecvBuf, sizeof(RecvBuf), 0);
    // ::MessageBox(NULL,"",RecvBuf,1);
     if(nRecv <= 0)
     goto error;
     if (strstr(RecvBuf,"#")!=NULL) 
     {
     goto error;
     }
     ret = DataSend(ServerSock, RecvBuf, nRecv);
     if(ret == 0 || ret != nRecv)
     goto error;
     }
     if(FD_ISSET(ServerSock, &Fd_Read))
     {
     nRecv = recv(ServerSock, RecvBuf, sizeof(RecvBuf), 0);
     if (strstr(RecvBuf,"#")!=NULL) 
     {
     goto error;
     }
     if(nRecv <= 0)
     goto error;
     ret = DataSend(ClientSock, RecvBuf, nRecv);
     if(ret == 0 || ret != nRecv)
     goto error;
     }
     }
     
     error:
         ::EnterCriticalSection(&section);        
     char clientCount[10];
     CThreadManageDlg* pDlgConfig=(CThreadManageDlg*)AfxGetMainWnd();   
     pDlgConfig->nTimes--;
     sprintf(clientCount,"目前有%d个用户连接到本机!", pDlgConfig->nTimes);
     pDlgConfig->m_clientCountWnd->SetWindowText(clientCount); 
         ::LeaveCriticalSection(&section); 
     closesocket(ClientSock);
       closesocket(ServerSock);  return 0;

    int WorkerThread::PortTransfer()
    {
     SOCKET ClientSock, ServerSock;
     //出栈,获得客户的套接字
     ClientSock = configPara.s;
     //先连接到目标计算机的服务
     ServerSock = ConnectHost(configPara.szIP, configPara.wPort);
     if(ServerSock <= 0)
     {
     printf("Error.\r\n");
     closesocket(ClientSock);
     return 0;
     }
     SOCKINFO socks;
     socks.ClientSock = ClientSock;//客户的套接字
     socks.ServerSock = ServerSock;//目标计算机服务的套接字
     //进入纯数据转发状态
     return TransmitData((LPVOID)&socks);
    }
    PortTransfer()是线程函数调用的函数,还有就是“目前有%d个用户连接到本机”不知道为什么 好比我开了400个连接,然后都关闭时显示当前还有75个连到本机,应该是都关闭的吧, 我试过用临界区 也不行 大侠们帮帮忙
      

  2.   

    你的服务器端口是只有一个ServerSock 么,如果是的话,你要创建的应该是一个数组才行,一般都是循环使用一个数组
      

  3.   

    你是说TransmitData函数里的
    SOCKET ClientSock = socks.ClientSock; 
    SOCKET ServerSock = socks.ServerSock; 
    这个ServerSock服务器端口吗,我不是只用一个,如果所有客户端都共享一个这个端口也不稳定,有时候能运行,有时候所有客户端都会掉,每个线程我重新连接一下web服务器,这个端口都不一样的,而且我试过如果把closesocket(ServerSock); 这一句注掉的话就没事。 一个不应该影响另一个线程的吧。
        如果按说的方法,应该把closesocket(ServerSock);这句注掉,会没有问题,那还有没有别的办法,它为什么会影响别的线程呢?我测试的那个客户端程序的代码我看过,它用WSAAsyncSelect检测FD_CLOSE事件,和它套接字相关的ClientSock 套接字和ServerSock 套接字没关,别的线程关了怎么会影响到,并发事件呢?
      

  4.   

    其它的套接字有可能是这个函数recv,如果是标准的socket它的函数有可能返回ret 是大于0的,但很大的可能是没有接收完的,一般来说我们都会自己对标准socket函数在封装一次,我觉得是你关闭了ServerSock 但它的数据实际上是没有接受完的
      

  5.   

    哦,不是很懂,你意思是标准socket在客户端退出再recv的时候返回值也有可能大于0,我不知道我用的是不是标准的,刚接触这东西,#pragma comment(lib, "ws2_32.lib") 我加了这个库,我操作的时候都是返回-1的,数据没有接受完就让另一个客户端退出啊,还有一个问题,当客户端退出时因为recv小于0,要退出线程函数时要操作当前用户数,我的代码有问题吗?它为什么不准确,是同步问题吗
      

  6.   

    不好意思,还有个问题,serversocket做成一个数组,web服务器端的session不是有时间限制吗?刚创建时不会超时但久了后服务器不就断开连接了吗,再往这个是serversocket发数据会不会有问题,要不要我定时对这个数组重新连接下web服务器呢?