c++中select模型

InitSock.h头文件

#pragma once
#include 
#pragma comment(lib,"ws2_32")       //链接ws2_32.lib库

class CInitSock
{
public:
    CInitSock(BYTE minorVer=2, BYTE major = 2)      //载入Winsock库
    {
        WSADATA wsaData;
        WORD sockVersion = MAKEWORD(minorVer, major);
        if (::WSAStartup(sockVersion, &wsaData) != 0)
        {
            return;
        }
    }
    ~CInitSock()
    {
        ::WSACleanup(); //释放Winsock库
    }
};
#include "InitSock.h"
#include 
using namespace std;


//select的好处是程序能够在单线程内同时处理多个套接字连接

int main()
{   
    CInitSock initSock; //初始化套接字库

    SOCKET sListen = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);   //创建监听套接字

    sockaddr_in addr;
    addr.sin_addr.S_un.S_addr = INADDR_ANY;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(4567);

    //套机字与本地机器绑定
    if (::bind(sListen, (sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR)
    {
        cout << "Faild bind" << endl;
        return -1;
    }

    ::listen(sListen, 5);//监听  最多等待5个连接

    //select模型
    fd_set fdSocket;    //套接字集合  ,默认最大值FD_SETSIZE
    FD_ZERO(&fdSocket); //初始化fd_set集合,集合在使用前应该清空
    FD_SET(sListen, &fdSocket); //将套接字添加到集合

    while (1)
    {
        fd_set fdRead = fdSocket;   //将一个套接字拷贝赋给select函数

        //用于接收数据
        int iRet = ::select(0, &fdRead, NULL, NULL, NULL);  //参数1:忽略,仅为了与Berkeley套机字兼容 
                                                            //参数2:用来检查可读性 
                                                            //参数3:用来检查可写性
                                                            //参数4:用来检查错误
                                                            //参数5:用来设置等待时间,NULL表示一直阻塞等待
                                                            //返回值:0表示超时,失败返回SOCKET_ERROR,调用成功返回发生网络事件的套接字数量总和
        if (iRet > 0)   //返回成功fdRead套接字集合会有变化
        {
            for (int i = 0; i < fdRead.fd_count; i++)
            {
                if (FD_ISSET(fdSocket.fd_array[i], &fdRead))    //检查fdSocket.fd_arry[i]是不是faRead的成员函数,成功返回TRUE
                {
                    if (fdSocket.fd_array[i] == sListen)    //监听套接字接收到新连接
                    {
                        if (fdSocket.fd_count < FD_SETSIZE) //判断是否小于select的最大数量
                        {
                            sockaddr_in addrRemote;
                            int iLen = sizeof(addrRemote);
                            SOCKET sNew = ::accept(sListen, (SOCKADDR*)&addrRemote, &iLen); //创建套接字与客户端通信
                            FD_SET(sNew, &fdSocket);    //新接收的连接添加到套接字集合
                            printf("接收到连接(%s)\n", ::inet_ntoa(addrRemote.sin_addr));

                        }
                        else                
                        {
                            //超过select的最大数量
                            printf("Too much connections \n");
                            continue;
                        }
                    }
                    else
                    {
                        char cText[256];
                        int iRecv = ::recv(fdSocket.fd_array[i], cText, strlen(cText),0);
                        if (iRecv > 0)
                        {
                            cText[iRecv] = '\0';
                            printf("接收的数据:%s\n", cText);
                        }
                        else
                        {
                            ::closesocket(fdSocket.fd_array[i]);    //连接关闭、重启、关闭
                            FD_CLR(fdSocket.fd_array[i], &fdSocket);    //从套接字集合fdSocket中删除fdSocket.fd_array[i]
                        }
                    }
                }
            }
        }
        else
        {
            printf("Faild select \n");
        }
    }


    return 0;
}

你可能感兴趣的:(c++中select模型)