Programación de red Linux (encuesta de multiplexación de IO múltiple)


prefacio

En el artículo anterior explicamos el uso de select para la multiplexación de IO, en este artículo explicaremos el uso de la función de encuesta para la multiplexación de IO múltiple.

1. Explicación de la función de encuesta.

La función poll() es una función de llamada al sistema comúnmente utilizada en la programación de redes. Se utiliza para monitorear el estado de múltiples descriptores de archivos para determinar si algún descriptor de archivo está listo para lectura, escritura o si ocurre una excepción.

以下是 poll() 函数的基本用法:

#include <poll.h>

int poll(struct pollfd *fds, nfds_t nfds, int timeout);

El parámetro fds es un puntero a una matriz de estructuras pollfd, cada estructura describe un descriptor de archivo y los eventos que le interesan.

El parámetro nfds es el número de elementos de la matriz fds.

El parámetro de tiempo de espera es el tiempo de espera en milisegundos. Especificar un valor para el tiempo de espera puede controlar el comportamiento de bloqueo de la función poll().

pollfd 结构体的定义如下:

struct pollfd {
    
    
    int fd;       // 文件描述符
    short events; // 感兴趣的事件
    short revents; // 实际发生的事件
};

fd es el descriptor del archivo que se está observando.

events 是要监视的事件的掩码,可以是以下值之一或它们的组合:

POLLIN: Hay datos para leer.

POLLOUT: se pueden escribir datos.

POLLERR: Se produjo un error.

POLLHUP: La conexión está cerrada.

POLLNVAL: El descriptor del archivo es ilegal.

revents son los eventos reales que completa la función poll().

poll() 函数的返回值表示有几个文件描述符准备好了,即满足所关心的事件。返回 值的三种情况如下:

Valor de retorno mayor que 0: indica el número de descriptores de archivos listos.

Un valor de retorno igual a 0: indica que ningún descriptor de archivo estaba listo dentro del tiempo de espera especificado.

El valor de retorno es menor que 0: ocurrió un error de ejecución.

使用 poll() 函数的步骤如下:

1. Configure los campos fd y events de cada descriptor de archivo en la matriz pollfd.

2. Llame a la función poll() y pase la matriz pollfd, el número de elementos y el tiempo de espera.

3. Verifique el valor de retorno y juzgue el evento específico de acuerdo con el campo revits.

2. Utilice la función de encuesta para completar el servidor concurrente.

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <poll.h>

#define MAX_CLIENT  1024//最大可连接客户端的数量

int main()
{
    
    
    int server = 0;
    struct sockaddr_in saddr = {
    
    0};
    int client = 0;
    struct sockaddr_in caddr = {
    
    0};
    socklen_t asize = 0;
    int len = 0;
    char buf[32] = {
    
    0};
    int maxfd;
    int ret = 0;
    int i = 0;

    server = socket(PF_INET, SOCK_STREAM, 0);

    if( server == -1 )
    {
    
    
        printf("server socket error\n");
        return -1;
    }

    saddr.sin_family = AF_INET;
    saddr.sin_addr.s_addr = htonl(INADDR_ANY);
    saddr.sin_port = htons(8888);

    if( bind(server, (struct sockaddr*)&saddr, sizeof(saddr)) == -1 )
    {
    
    
        printf("server bind error\n");
        return -1;
    }

    if( listen(server, 128) == -1 )
    {
    
    
        printf("server listen error\n");
        return -1;
    }

    printf("server start success\n");

	/*将fds中的fd全部置为-1*/
    struct pollfd fds[MAX_CLIENT];
    for(i = 0; i < MAX_CLIENT; i++)
    {
    
    
        fds[0].fd = -1;
    }

    /*将服务端套接字添加到fds数组中*/
    fds[0].fd = server;
    fds[0].events = POLLIN;

    while( 1 )
    {
    
            
        ret = poll(fds, MAX_CLIENT, -1);
        if(ret < 0)
        {
    
    
            printf("poll err\n");
            return -1;
        }

        if(fds[0].revents & POLLIN)
        {
    
    
            /*有客户端连接上来了*/
            asize = sizeof(caddr);  
            client = accept(server, (struct sockaddr*)&caddr, &asize);
            printf("client is connect\n");

            /*将新连接添加到fds数组中*/
            for(i = 1; i < MAX_CLIENT; i++)
            {
    
    
                if(fds[i].fd == -1)
                {
    
    
                    fds[i].fd = client;
                    fds[i].events = POLLIN;
                    break;
                }
            }            
        }

        /*遍历现有连接进行读取和处理数据*/
        for(i = 1; i < MAX_CLIENT; i++)
        {
    
                
            int clientfd = fds[i].fd;
            if(clientfd > 0 && (fds[i].revents & POLLIN))
            {
    
    
                printf("process data\n");
                len = read(clientfd, buf, 1024);
                if(len == 0)
                {
    
    
                    /*客户端断开连接,关闭客户端文件描述符*/
                    close(clientfd);
                    fds[i].fd = -1;
                    printf("client is disconnect\n");
                }
                else
                {
    
    
                    printf("read buf : %s\n", buf);
                    write(clientfd, buf, len);
                }
            }
        }
    }
    
    close(server);

    return 0;
}

3. Ventajas y desventajas de la encuesta.

优点:

1. Facilidad de uso: en comparación con llamadas al sistema de bajo nivel como select, poll proporciona una API más simple, que es más fácil de usar y comprender.

2. No hay límite en la cantidad de descriptores de archivos: la encuesta no tiene un límite predefinido en la cantidad de descriptores de archivos y puede adaptarse a conexiones concurrentes a mayor escala.

3. Admite una matriz de descriptores de archivos: en comparación con el método de selección de mapa de bits, la encuesta utiliza una matriz de descriptores de archivos, que se puede administrar y operar de manera más conveniente.

4. Eficiente: la encuesta utiliza el sondeo para monitorear los cambios de estado de los descriptores de archivos. Solo se devolverán los descriptores de archivos activos, lo que reduce los procesos de sondeo inútiles y mejora la eficiencia.

5. Admite IO sin bloqueo: similar a la selección, la encuesta también admite el modo IO sin bloqueo, que puede continuar procesando otras tareas durante el período de espera.

缺点:

1. Cada llamada requiere atravesar toda la matriz de descriptores de archivos: incluso si solo unos pocos descriptores de archivos están activos, la encuesta debe atravesar toda la matriz de descriptores de archivos cada vez que se llama, lo que provocará una sobrecarga de rendimiento.

2. No se proporciona control de precisión del tiempo de espera: el parámetro de tiempo de espera de la encuesta está en milisegundos y no puede proporcionar una mayor precisión, por lo que no es adecuado cuando se requiere un tiempo de espera más preciso.

3. No portabilidad: la encuesta es una llamada al sistema relativamente nueva. No todos los sistemas operativos proporcionan esta interfaz, por lo que se debe considerar la compatibilidad al escribir código multiplataforma.

4. Sin soporte para el procesamiento de señales: a diferencia de select, poll no brinda soporte para el procesamiento de señales, por lo que no puede procesar directamente eventos de señales.

Resumir

Este artículo explica principalmente cómo usar la función de encuesta y cómo usar la encuesta para implementar un servidor concurrente. Puede compararlo y pensar en esto junto con la función de selección en el artículo anterior.

Supongo que te gusta

Origin blog.csdn.net/m0_49476241/article/details/132368785
Recomendado
Clasificación