c++ select模型

在掌握了socket相关的一些函数后,套接字编程还是比较简单的,日常工作中碰到很多的问题就是客户端/服务器模型中,如何让服务端在同一时间高效的处理多个客户端的连接,我们的处理办法可能会是在服务端不停的监听客户端的请求,有新的请求到达时,开辟一个新的线程去和该客户端进行后续处理,但是这样针对每一个客户端都需要去开辟一个新的线程,效率必定底下。

     其实,socket编程提供了很多的模型来处理这种情形,我们只要按照模型去实现我们的代码就可以解决这个问题。主要有select模型和重叠I/o模型,以及完成端口模型。这次,我们主要介绍下select模型,该模型又分为普通select模型,wsaasyncselect模型,wsaeventselect模型。我们将通过样例代码的方式逐一介绍。

一、select模型

使用该模型时,在服务端我们可以开辟两个线程,一个线程用来监听客户端的连接

请求,另一个用来处理客户端的请求。主要用到的函数为select函数。如:

全局变量:

fd_set  g_fdClientSock;

线程1处理函数:

复制代码
    SOCKET listenSock = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );

    sockaddr_in sin;
    sin.sin_family = AF_INET;
    sin.sin_port = htons(7788);
    sin.sin_addr.S_un.S_addr = INADDR_ANY;

    int nRet = bind( listenSock, (sockaddr*)&sin, (int)(sizeof(sin)));
    if ( nRet == SOCKET_ERROR )
    {
        DWORD errCode = GetLastError();
        return;
    }

    listen( listenSock, 5);

    int clientNum = 0;

    sockaddr_in clientAddr;

    int nameLen = sizeof( clientAddr );

    while( clientNum < FD_SETSIZE )
    {
        SOCKET clientSock = accept( listenSock, (sockaddr*)&clientAddr, &nameLen );
        FD_SET( clientSock, &g_fdClientSock);
        clientNum++;
     }
复制代码

线程2处理函数:

复制代码
    fd_set fdRead;
    FD_ZERO( &fdRead );
    int nRet = 0;
    char* recvBuffer =(char*)malloc( sizeof(char) * 1024 );

    if ( recvBuffer == NULL )
    {
        return;
    }

    memset( recvBuffer, 0, sizeof(char) * 1024 );
    while ( true )
    {
        fdRead = g_fdClientSock;
        nRet = select( 0, &fdRead, NULL, NULL, NULL );
        if ( nRet != SOCKET_ERROR )
        {
            for ( int i = 0; i < g_fdClientSock.fd_count; i++ )
            {
                if ( FD_ISSET(g_fdClientSock.fd_array[i],&fdRead)  )
                {
                    memset( recvBuffer, 0, sizeof(char) * 1024 );
                    nRet = recv( g_fdClientSock.fd_array[i], recvBuffer, 1024, 0);
                    if ( nRet == SOCKET_ERROR )
                    {
                        closesocket( g_fdClientSock.fd_array[i] );
                            FD_CLR( g_fdClientSock.fd_array[i], &g_fdClientSock );
                    }
                    else
                    {
                        //todo:后续处理
                       }
                }
            }
        }
    }

    if ( recvBuffer != NULL )
    {
        free( recvBuffer );
    }
复制代码

该模型有个最大的缺点就是,它需要一个死循环不停的去遍历所有的客户端套接字集合,询问是否有数据到来,这样,如果连接的客户端很多,势必会影响处理客户端请求的效率,但它的优点就是解决了每一个客户端都去开辟新的线程与其通信的问题。如果有一个模型,可以不用去轮询客户端套接字集合,而是等待系统通知,当有客户端数据到来时,系统自动的通知我们的程序,这就解决了select模型带来的问题了。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值