一、select模型特点
select是传统的IO多路复用模型,与其他IO多路复用模型(如epoll,kqueue)不同的是,select函数能够同时监听多个socket句柄的可读、可写和异常等事件。当某个socket句柄上的事件发生变化时,select函数就会返回,并将所有发生变化的socket句柄集合返回给用户程序,用户程序可以通过遍历这个集合来逐个处理socket事件。
select模型具有较好的兼容性,在大多数操作系统和编程语言中都有实现。同时,由于是同步阻塞模型,所以在并发访问不太密集的场景下,具有较好的稳定性。
但是,由于select模型每次只能监听1024个socket句柄(Windows下更少),因此在高并发访问的场景下,不太适合使用。
二、在IO多路复用模型中使用select
在IO多路复用模型中,使用select函数来监听多个socket句柄的事件,等待有事件发生时处理这些事件。
首先需要用fd_set数据类型来表示要监听的socket集合,通常只需要用到其中的“读就绪”信号。通过调用select函数,并传入要监听的socket集合(也可以分成多个集合)以及超时时间,等待其中任何一个socket句柄的事件发生。
当select函数返回时,需要遍历返回的socket集合,并逐个处理事件,比如接收客户端连接请求、读取数据、写入数据等操作。
三、select模型的作用
select模型的主要作用是实现并发访问和事件监听,并且既可以用于客户端,也可以用于服务器端。
在服务器端,select模型可以监听多个客户端的请求,并响应这些请求。通过即时地处理请求,可以大大提高服务器端的响应能力和并发处理能力,实现高性能的服务器端应用。
在客户端,select模型可以实现同时请求多个资源,提高访问效率,减少用户等待时间。
四、select模型的应用场景
由于select模型在IO多路复用模型中最古老、最基础,因此在某些场景下,仍然可能是最佳选择。
比如在简单的网络应用中,select模型可以通过监听多个连接,实现并发访问和快速响应。在一些低流量场景下,由于没有高并发访问,因此可以保证稳定性。
同时,在学习网络编程时,也可以先从select模型开始,了解IO多路复用模型的基础知识。
五、select模型服务器
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/time.h>
#define BUF_SIZE 100
int main(int argc, char *argv[])
{
    int serv_sock, clnt_sock;
    struct sockaddr_in serv_adr, clnt_adr;
    socklen_t adr_sz;
    int fd_max, str_len, fd_num, i;
    char buf[BUF_SIZE];
    fd_set reads, cpy_reads;
    struct timeval timeout;
    if(argc!=2) {
        printf("Usage : %s \n", argv[0]);
        exit(1);
    }
    serv_sock=socket(PF_INET, SOCK_STREAM, 0);   
    memset(&serv_adr, 0, sizeof(serv_adr));
    serv_adr.sin_family=AF_INET;    
    serv_adr.sin_addr.s_addr=htonl(INADDR_ANY);
    serv_adr.sin_port=htons(atoi(argv[1]));
    if(bind(serv_sock, (struct sockaddr*)&serv_adr, sizeof(serv_adr))==-1)
        exit(1);
    if(listen(serv_sock, 5)==-1)
        exit(1);
    FD_ZERO(&reads);
    FD_SET(serv_sock, &reads);
    fd_max=serv_sock;
    while(1)
    {
        cpy_reads=reads;
        timeout.tv_sec=5;
        timeout.tv_usec=5000;
        if((fd_num=select(fd_max+1, &cpy_reads, 0, 0, &timeout))==-1)
            break;
        if(fd_num==0)
            continue;
        for(i=0; i<fd_max+1; i++)
        {
            if(FD_ISSET(i, &cpy_reads))
            {
                if(i==serv_sock)  // connection request!
                {
                    adr_sz=sizeof(clnt_adr);
                    clnt_sock=accept(serv_sock, (struct sockaddr*)&clnt_adr, &adr_sz);
                    FD_SET(clnt_sock, &reads);
                    if(fd_max<clnt_sock)
                        fd_max=clnt_sock;
                    printf("connected client: %d \n", clnt_sock);
                }
                else    // read message!
                {
                    str_len=read(i, buf, BUF_SIZE);
                    if(str_len==0)    // close request!
                    {
                        FD_CLR(i, &reads);
                        close(i);
                        printf("closed client: %d \n", i);
                    }
                    else
                    {
                        write(i, buf, str_len);    // echo!
                    }
                }
            }
        }
    }
    close(serv_sock);
    return 0;
}
六、select模型工作原理
select模型基于IO多路复用机制,使用select函数来监听多个socket句柄的事件,等待有事件发生时处理这些事件。当有事件发生时,select函数就会返回,并将所有发生变化的socket句柄集合返回给用户程序,用户程序可以通过遍历这个集合来逐个处理socket事件。
在实现过程中,需要用fd_set数据类型来表示要监听的socket集合,通过调用select函数,并传入要监听的socket集合以及超时时间,等待其中任何一个socket句柄的事件发生。当select函数返回时,需要遍历返回的socket集合,并逐个处理事件。
七、我们所熟知的网络IO模型select
在网络编程中,select模型是最早、也是最为流行的网络IO模型之一。
select模型的核心思想是使用select函数来监听多个socket句柄,等待它们的读写ready事件,从而实现并发收发数据,提高网络传输效率。
由于其简单易懂、兼容性强、用途广泛,因此仍然被广泛应用在各类网络应用中。
八、select模型的编程步骤
使用select模型进行网络编程的步骤如下:
1. 创建socket。
2. 初始化(绑定)socket地址。
3. 调用listen函数,将socket设置为监听状态,等待客户端连接请求。
4. 创建fd_set类型的变量,用于存储要监听的socket集合。
5. 将要监听的socket加入到fd_set类型变量中。
6. 调用select函数,等待socket事件发生,返回有事件发生的socket集合。
7. 遍历socket集合,处理所有事件。
8. 关闭socket。
九、select模型能突破1024吗?
select模型最多只能监听1024个socket句柄,无法处理更大的并发访问量。为了解决这个问题,后来出现了更先进的IO多路复用模型,比如epoll和kqueue,它们能够监听更多的socket句柄。
虽然select模型的并发能力相对较弱,但在某些场景下仍然有其独特的优势,比如在低流量、低并发的网络应用中。
结语
以上是对select模型的详细阐述,希望能够对读者理解IO多路复用模型、网络编程等方面有所启发。同时,本文也为读者提供了一个基于select模型的简单服务器端代码示例。
原创文章,作者:QROTG,如若转载,请注明出处:https://www.506064.com/n/371885.html
微信扫一扫 
支付宝扫一扫