select模型简介(windowns系统下的编程)

本文介绍了select模型在IT技术中的优点,如跨平台性、简单易用和灵活性,但也指出其在大规模并发和效率方面的局限。同时提供了使用select模型进行网络编程的基本步骤。
摘要由CSDN通过智能技术生成

select模型的优点:

1. 跨平台性: select 模型是跨平台的,几乎所有的操作系统都支持 select 模型,包括 Linux Windows 等。
2. 简单易用: select 模型的 API 相对简单,使用起来比较方便,适用于简单的网络编程需求。
3. 灵活性: select 模型支持监视多个文件描述符,并且可以通过设置超时参数来实现超时等待,具有一定的灵活性。
4. 可移植性: select 模型是标准的 POSIX 函数,具有较好的可移植性,适用于各种不同平台的开发。

select模型的缺点:

1. 效率低: select 模型在大规模并发的场景下效率较低,因为需要遍历所有的文件描述符,性能随着监视的文件描述符数量增加而下降。
2. 文件描述符数量限制: select 模型对监视的文件描述符数量有限制,通常最多支持 1024 个,超过这个数量会导致程序崩溃或运行异常。
3. IO 效率不高: select 模型每次都需要将监视的所有文件描述符传递给内核,效率较低,特别是在文件描述符数量较大时。

使用select模型的步骤方法:

1. 准备文件描述符集合: 使用 fd_set 类型的变量准备需要监视的文件描述符集合。
2. 设置超时参数(可选): 可以设置超时参数,指定 select 函数的等待时间,超时后 select 函数返回。
3. 调用 select 函数: 调用 select 函数进行文件描述符的监视,等待有事件发生。
4. 检查事件类型: 使用 FD_ISSET 宏检查每个文件描述符对应的事件类型,判断事件的类型。
5. 处理事件: 根据事件的类型进行相应的处理,比如接收数据、发送数据等。
6. 重复调用 select 函数: 如果有需要,可以重复调用 select 函数,持续监视文件描述符的状态,直到程序结束。

总的来说,select模型适用于简单的网络编程需求,但在处理大规模并发连接时效率较低,不适合高性能的网络编程场景。

#include <iostream>
#include <string>
#include <WS2tcpip.h>
#include <vector>
#include <algorithm>
#pragma comment(lib, "ws2_32.lib")

int main() {
    // 初始化Winsock
    WSADATA wsData;
    WORD ver = MAKEWORD(2, 2);
    int wsOK = WSAStartup(ver, &wsData);
    if (wsOK != 0) {
        std::cerr << "Error: Can't initialize Winsock! Quitting" << std::endl;
        return 1;
    }

    // 创建监听socket
    SOCKET listener = socket(AF_INET, SOCK_STREAM, 0);
    if (listener == INVALID_SOCKET) {
        std::cerr << "Error: Can't create listener socket! Quitting" << std::endl;
        WSACleanup();
        return 1;
    }

    // 绑定地址和端口
    sockaddr_in hint;
    hint.sin_family = AF_INET;
    hint.sin_port = htons(54000);
    hint.sin_addr.S_un.S_addr = INADDR_ANY; // 监听所有网卡上的连接
    bind(listener, (sockaddr*)&hint, sizeof(hint));

    // 开始监听
    listen(listener, SOMAXCONN);

    // 设置fd_set,包含监听socket和所有活跃socket
    fd_set master;
    FD_ZERO(&master);
    FD_SET(listener, &master);

    // 记录活跃的客户端socket
    std::vector<SOCKET> clients;

    std::cout << "Server listening..." << std::endl;

    while (true) {
        fd_set copy = master;

        // 使用select检查socket的状态
        int socketCount = select(0, &copy, nullptr, nullptr, nullptr);

        for (int i = 0; i < socketCount; ++i) {
            SOCKET sock = copy.fd_array[i];

            // 如果是监听socket有新连接
            if (sock == listener) {
                SOCKET client = accept(listener, nullptr, nullptr);

                // 将新客户端socket添加到master集合中
                FD_SET(client, &master);
                clients.push_back(client);

                std::cout << "New client connected" << std::endl;
            }
            else {
                
                // 处理客户端发来的消息
                char buffer[4096];
                memset(buffer, 0, sizeof(buffer));
                int bytesReceived = recv(sock, buffer, sizeof(buffer), 0);
                if (bytesReceived <= 0) {
                    // 客户端关闭连接
                    std::cout << "Client disconnected" << std::endl;
                    closesocket(sock);
                    FD_CLR(sock, &master);
                    clients.erase(std::remove(clients.begin(), clients.end(), sock), clients.end());
                }
                else {
                    // 将消息打印到控制台
                    std::cout << "Received from client: " << std::string(buffer, bytesReceived) << std::endl;

                    // 将消息发送给其他所有客户端
                    for (SOCKET outSock : clients) {
                        if (outSock != listener && outSock != sock) {
                            send(outSock, buffer, bytesReceived, 0);
                        }
                    }
                }
            }
        }
    }

    // 关闭监听socket
    closesocket(listener);

    // 关闭Winsock
    WSACleanup();

    return 0;
}

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值