c++中select模型

InitSock.h头文件

#pragma once
#include <winsock2.h>
#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 <iostream>
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;
}
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • mean to add the formatted="false" attribute?.[ 46% 47325/...
    ProZoom阅读 7,931评论 0 3
  • 一、C++ 编译模式 通常,在一个 C++ 程序中,只包含两类文件―― .cpp 文件和 .h 文件。其中,.cp...
    胡一巴阅读 4,498评论 0 1
  • 这是HR面试我的一道题,没技术上含量,不过细想起来,还是C语言的最基本的知识!俗话说,目标决定动力,细节决定成败!...
    闭家锁阅读 14,918评论 0 5
  • 接口规定了模块做什么,仅规定应用程序可能使用的那些标识符,而尽可能隐藏不相关的表示细节和算法。在C语言中,接口通过...
    cli1871阅读 13,018评论 0 3
  • 转载文章:C++中的头文件和源文件 一、C++编译模式 通常,在一个C++程序中,只包含两类文件——.cpp文件和...
    Mr希灵阅读 10,268评论 1 10

友情链接更多精彩内容