select 非阻塞模式 服务器 代码


//   TCP Server select非阻塞模式
//   IP: 127.0.0.1
//   PORT: 1207
#define LISTEN_IP    "127.0.0.1"
#define LISTEN_PORT 1207
#define DEFAULT_BUFF 256
#define MAX_LISTEN   2    //最多可同时连接的客户端数量
int g_fd_ArrayC[MAX_LISTEN] = {0}; //处理所有的待决连接
int _tmain(int argc, _TCHAR* argv[])
{
    WSAData        wsData;
    SOCKET         sListen;
    SOCKET         sClient;
    SOCKADDR_IN    addrListen;
    SOCKADDR_IN    addrClient;
    int            addrClientLen = sizeof(addrClient);
    char           recvBuff[DEFAULT_BUFF] = {0};
    char           responseBuff[DEFAULT_BUFF] = {"Server Has Received"};
    char           noresponseBuff[DEFAULT_BUFF] = {"服务器端连接数已满,无法连接"};
    int            nRes = 0;
    printf(">>>>>TCP 服务器端启动<<<<<<\n");
    WSAStartup(MAKEWORD(2,2), &wsData);
    printf("-创建一个SOCKET\n");
    sListen = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
    if(sListen==INVALID_SOCKET)
    {
        printf("!!! socket failed: %d\n", WSAGetLastError());
        WSACleanup();
        return -1;
    }
    printf("-设定服务器监听端口\n");
    addrListen.sin_family = AF_INET;
    addrListen.sin_addr.S_un.S_addr = inet_addr( LISTEN_IP );
    addrListen.sin_port = htons( LISTEN_PORT );
    printf("-绑定SOCKET与指定监听端口: %s:%d\n", inet_ntoa(addrListen.sin_addr), ntohs(addrListen.sin_port));
    nRes = bind( sListen, (const sockaddr*)&addrListen, sizeof(addrListen) );
    if( nRes == SOCKET_ERROR )
    {
        printf("!!! bind failed: %d\n", WSAGetLastError());
        closesocket( sListen );
        WSACleanup();
        return -1;
    }
    printf("-监听端口\n");
    nRes = listen( sListen, MAX_LISTEN );
    if( nRes == SOCKET_ERROR )
    {
        printf("!!! listen failed: %d\n", WSAGetLastError());
        closesocket( sListen );
        WSACleanup();
        return -1;
    }
    /
    // 非阻塞模式设定
    //
    /
    DWORD nMode = 1;
    nRes = ioctlsocket( sListen, FIONBIO, &nMode );
    if( nRes == SOCKET_ERROR )
    {
        printf("!!! ioctlsocket failed: %d\n", WSAGetLastError());
        closesocket( sListen );
        WSACleanup();
        return -1;
    }
    printf("-设置服务器端模式: %s\n", nMode==0? "阻塞模式":"非阻塞模式");

    printf("-开始准备接受连接\n");
    fd_set fdRead;
    fd_set fdWrite;
    timeval tv={10,0};
    int     nLoopi = 0;
    int     nConnNum = 0;
    while(true)
    {
        printf("-select 开始\n");
        FD_ZERO(&fdRead, &fdWrite);
        FD_SET( sListen, &fdRead ); 
        //将待决的连接SOCKET放入fdRead集中进行select监听

//每次进入循环都要没空,重设
        for( nLoopi=0; nLoopi<MAX_LISTEN; ++nLoopi )
        {
            if( g_fd_ArrayC[nLoopi] !=0 )
            {
                printf("-LOOPI: 待决SOCKET: %d\n",g_fd_ArrayC[nLoopi] );
                FD_SET( g_fd_ArrayC[nLoopi], &fdRead );
            }
        }
        //调用select模式进行监听
        nRes = select( 0, &fdRead, NULL, NULL, &tv );
        ;;;;;if( nRes == 0 )
        {
            printf("-!!! select timeout: %d sec\n",tv.tv_sec);
            continue; //继续监听
        }
        else if( nRes < 0 )
        {
            printf("!!! select failed: %d\n", WSAGetLastError());
            break;
        }

        //检查所有的可用SOCKET
        printf("-查找可用的SOCKET\n");
        for( nLoopi=0; nLoopi<MAX_LISTEN; ++nLoopi )
        {
            if( FD_ISSET(g_fd_ArrayC[nLoopi], &fdRead) )
            {
                memset( recvBuff, 0 ,sizeof(recvBuff) );
                nRes = recv( g_fd_ArrayC[nLoopi], recvBuff, sizeof(recvBuff)-1, 0 );
                if( nRes <= 0 )
                {
                    printf("-Client Has Closed.\n");
                    closesocket( g_fd_ArrayC[nLoopi] );
                    //将已经关闭的SOCKET从FD集中删除
                    FD_CLR( g_fd_ArrayC[nLoopi], &fdRead );
                    g_fd_ArrayC[nLoopi] = 0;
                    --nConnNum;
                }
                else
                {
                    recvBuff[nRes] = '\0';
                    printf("-Recvied: %s\n", recvBuff);
                    send( g_fd_ArrayC[nLoopi], responseBuff, strlen(responseBuff), 0 ); 
                }
            }
        }//for( nLoopi=0; nLoopi<MAX_LISTEN; ++nLoopi )

        //检查是否为新的连接进入
        if( FD_ISSET( sListen, &fdRead) )
        {
            printf("-发现一个新的客户连接\n");
            sClient = accept( sListen, (sockaddr*)&addrClient, &addrClientLen );
            ;;;;;if( sClient == WSAEWOULDBLOCK )
            {
                printf("!!! 非阻塞模式设定 accept调用不正\n");
                continue;
            }
            else if( sClient == INVALID_SOCKET )
            {
                printf("!!! accept failed: %d\n", WSAGetLastError());
                continue;
            }
            //新的连接可以使用,查看待决处理队列
            if( nConnNum<MAX_LISTEN )
            {
                for(nLoopi=0; nLoopi<MAX_LISTEN; ++nLoopi)
                {
                    if( g_fd_ArrayC[nLoopi] == 0 )
                    {//添加新的可用连接
                        g_fd_ArrayC[nLoopi] = sClient;
                        break;
                    }
                }
                ++nConnNum;
                printf("-新的客户端信息:[%d] %s:%d\n", sClient, inet_ntoa(addrClient.sin_addr), ntohs(addrClient.sin_port));
            }
            else
            {
                printf("-服务器端连接数已满: %d\n", sClient);
                send( sClient, noresponseBuff, strlen(noresponseBuff), 0 );
                closesocket( sClient );
            }
        }//if( FD_ISSET( sListen, &fdRead) )
    }//while(true)
    printf("-关闭服务器端SOCKET\n");
    closesocket( sListen );
    WSACleanup();
return 0;
}


原文转自http://hi.baidu.com/duycllvljladfrr/item/9d0f02d4868d1ed4241f40a2

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值