2011-05-03 91 views
2

我正在使用C++在Windows平台上开发客户端服务器程序,如下所示。可以在单个tcp客户端服务器程序中允许多个select()

1.我有远程数据中心(服务器)。
2.我有一个连接数据中心(tcp)的网关(客户端)。
3.我有一个远程管理网关的gui应用程序。

所以这里的GUI Gateway是Server。

我做下面的事情

我在网关两个侦听器线程其中每个线程选择()系统调用被调用。

  1. 数据中心监听线程 - 这将招待数据中心的数据。
  2. GUI监听器线程 - 这将娱乐来自GUI的数据。

当我启动网关时,两个监听器自动启动并侦听来自数据中心和GUI的连接和数据。

网关与数据中心连接并接收数据。 BUt当我启动gui应用程序并尝试连接连接返回0但它不会在网关中的GUI侦听器线程中调用accept。

  1. 这是由于应用程序中的两个选择系统调用的问题吗?
  2. 如果是这样的话,是什么意思?

    void* CConnectionMgr::ListnerThreadDataCenter(void* args) 
    { 
    CGatewayInstanceManager* pGatewayInstance = (CGatewayInstanceManager*)args; 
    
    fd_set fdRead; 
    fd_set fdExcept; 
    
    int nSelectRetVal = 0; 
    
    timeval tv; 
    tv.tv_sec = 2; 
    tv.tv_usec = 0; 
    
    while(true) 
    { 
    FD_ZERO(&fdRead);  
    FD_ZERO(&fdExcept); 
    GatewayConnection::iterator itrGatewayCon; 
    GatewayConnection mapGatewayConn = pGatewayInstance->GetConnectionMgr()->GetGatewayConnection(); 
    itrGatewayCon = mapGatewayConn.begin(); 
    
    while (itrGatewayCon != mapGatewayConn.end()) 
    { 
        FD_SET (itrGatewayCon->second,&fdRead);  
        FD_SET (itrGatewayCon->second,&fdExcept); 
        itrGatewayCon++; 
    } 
    nSelectRetVal = select(NULL,&fdRead,NULL,&fdExcept,&tv); 
    
    // demultiplexing the socket for in coming message 
    if (nSelectRetVal>0) 
    { 
        for (itrGatewayCon = mapGatewayConn.begin();itrGatewayCon!= mapGatewayConn.end();itrGatewayCon++) 
        { 
          //Reading packet from the socket 
          unsigned char* pPacket = pGatewayInstance->GetConnectionMgr()->ReadPacketDataFromSocket(itrGatewayCon->second); 
          CProtocolMgr objProtocol; 
          CMessage* pMessage = objProtocol.ParseMsg(pPacket); 
          pGatewayInstance->HandleRequest(pMessage); 
        } 
    
    } 
    DWORD dwWaitResult;  
    dwWaitResult = WaitForSingleObject(ghListenerThreadDataCenterShutdownEvent,WAIT_TIME); 
    if (WAIT_OBJECT_0 == dwWaitResult) 
        break;  
    } 
    
    return 0; 
        } 
    
    
    
    void* CConnectionMgr::ListnerThreadUI(void* args) 
    { 
    CGatewayInstanceManager* pGatewayInstance = (CGatewayInstanceManager*)args; 
    fd_set fdRead; 
    fd_set fdExcept; 
    
    int nSelectRetVal = 0; 
    
    timeval tv; 
    tv.tv_sec = 2; 
    tv.tv_usec = 0; 
    while(true) 
    { 
    FD_ZERO(&fdRead);  
    FD_ZERO(&fdExcept); 
    if (pGatewayInstance->GetConnectionMgr()->GetServerSocket()!=-1) 
    { 
        FD_SET (pGatewayInstance->GetConnectionMgr()->GetServerSocket(),&fdRead);  
        FD_SET (pGatewayInstance->GetConnectionMgr()->GetServerSocket(),&fdExcept); 
    } 
    
    UIConnection::iterator itrUIConnection; 
    UIConnection listUIConnection = pGatewayInstance->GetConnectionMgr()->GetUIConnection();   
    for(itrUIConnection = listUIConnection.begin();itrUIConnection != listUIConnection.end();itrUIConnection++) 
    {   
        if (*itrUIConnection != -1) 
        { 
         FD_SET (*itrUIConnection,&fdRead);  
         FD_SET (*itrUIConnection,&fdExcept); 
        } 
    } 
    // demultiplexing the socket for in coming message 
    nSelectRetVal = select(NULL,&fdRead,NULL,&fdExcept,&tv);  
    if(nSelectRetVal>0) 
    {   
        if (FD_ISSET(pGatewayInstance->GetConnectionMgr()->GetServerSocket(),&fdRead)) 
        { 
         // accepting and new client and updating the UIConnection List 
         int nAcceptRetVal = 0;    
         nAcceptRetVal = pGatewayInstance->GetConnectionMgr()->ManageConnection(pGatewayInstance->GetConnectionMgr()); 
         continue;    
        } 
        if (FD_ISSET(pGatewayInstance->GetConnectionMgr()->GetServerSocket(),&fdExcept)) 
        { 
    
        }   
        for(itrUIConnection = listUIConnection.begin();itrUIConnection != listUIConnection.end();itrUIConnection++) 
        { 
         if (FD_ISSET(*itrUIConnection,&fdRead)) 
         { 
          //Reading packet from the socket 
          //string strPacket = pGatewayInstance->GetConnectionMgr()->ReadPacketDataFromSocket(*itrUIConnection); 
          //pGatewayInstance->HandleRequest(); 
         }    
        } 
    } 
    DWORD dwWaitResult;  
    dwWaitResult = WaitForSingleObject(ghListenerThreadUIShutDownEvent,WAIT_TIME); 
    if (WAIT_OBJECT_0 == dwWaitResult) 
        break;  
        } 
        return 0; 
        } 
    int CConnectionMgr::ManageConnection(CConnectionMgr* pConMgr) 
    { 
        sockaddr_in addrConnectedPeer; 
        int nAddrLen =sizeof(addrConnectedPeer) ; 
        int nAcceptRetVal = accept(pConMgr->GetServerSocket(),(sockaddr*)&addrConnectedPeer,&nAddrLen); 
        if (nAcceptRetVal>0) 
        { 
        pConMgr->AddUIConnection(nAcceptRetVal);  
        } 
        return 0; 
    } 
    

回答

2

你检查你的选择实施手册?因为select通常会将第一个param设置为最高的fd +1。 请参阅:http://www.manpagez.com/man/2/select/

基本上,select可以在应用程序中多次使用,但fd-masks(参数2,3,4)应该不同 - 否则输入的处理将被复制。

编辑:

的返回值0表示一个超时,在任何指定的FDS的无活性。

HTH马里奥

+1

我工作的窗口平台,并不需要FD +1 – 2011-05-03 05:05:48

+0

的0 RETVAL意味着没有套接字准备好,没有什么happend,任何套接字超时perhapse? – 2011-05-03 07:46:06

+0

返回0意味着连接成功http://black.goucher.edu/~kelliher/cs43/mar19.html – 2011-05-03 11:23:40

相关问题