gpt4 book ai didi

c++ - 单个tcp客户端服务器程序中是否允许多个select()

转载 作者:可可西里 更新时间:2023-11-01 02:41:47 25 4
gpt4 key购买 nike

我正在使用c++在windows平台上开发客户端服务器程序,如下所示。

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

因此这里的 GUI 网关是服务器。

我做了以下事情

我在网关中有两个监听器线程,在每个线程中调用 select() 系统调用。

  1. 数据中心监听器线程 - 这将处理来自数据中心的数据。
  2. GUI 监听器线程 - 这将处理来自 GUI 的数据。

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

网关连接到数据中心并接收数据。但是当我启动 gui 应用程序并尝试连接时,连接返回 0,但它不会在网关的 GUI 监听器线程中调用接受。

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

最佳答案

您是否查看了所选实现的手册?因为select通常期望第一个param是最高的fd+1。看这里:http://www.manpagez.com/man/2/select/

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

编辑:

返回值 0 表示超时,任何指定的 fds 上都没有事件。

马里奥

关于c++ - 单个tcp客户端服务器程序中是否允许多个select(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5864916/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com