当前位置:网站首页>Multiplexing IO

Multiplexing IO

2022-06-09 22:02:00 Gy648

multiple io Reuse --select

This method can monitor multiple file descriptors at the same time and the process is blocked , Once a file descriptor is detected, it is ready ( Can read data or write data ) The program will be unblocked , Then you can base on these ( One or more ) Ready file descriptors communicate

select

The delegate kernel helps us detect the status of several file descriptors

#include <sys/select.h>
struct timeval {
    
    time_t      tv_sec;         /* seconds */
    suseconds_t tv_usec;          // Initialization required , Otherwise it is a random value  /* microseconds */
};

int select(int nfds, fd_set *readfds, fd_set *writefds,
           fd_set *exceptfds, struct timeval * timeout);

nfds: The largest file descriptor of the three sets that the delegate kernel detects + 1, The kernel needs to traverse the file descriptors in these sets linearly , This value is Conditions at the end of the cycle stay Window This parameter in is invalid , Designated as - 1 that will do

readfds: Collection of file descriptors , The kernel only detects the read buffer corresponding to the file descriptor in this set so that it knows which file descriptor to receive data through

writefds: Collection of file descriptors , The kernel only detects the write buffer corresponding to the file descriptor in this collection , If you do not need to use this parameter, you can specify NULL

exceptfds: Collection of file descriptors , The kernel detects whether the file descriptor in the collection has an abnormal state , If you do not need to use this parameter, you can specify NULL

timeout: Time out period , Used to force the release of select () Function blocking
NULL: The function does not detect a ready file descriptor and will block all the time .
Wait for a fixed length of time ( second ): The function cannot detect a ready file descriptor , Force unblocking after a specified length of time , The function returns 0
Don't wait for : Functions don't block , Directly initialize the structure corresponding to this parameter to 0 that will do .
Function return value :
Greater than 0: success , Returns the total number of ready file descriptors in the collection
be equal to - 1: Function call failed
be equal to 0: Overtime , No ready file descriptor detected

void FD_CLR(int fd, fd_set *set);//  File descriptors fd from set Delete... From the collection  ==  take fd The corresponding flag bit is set to 0 
int  FD_ISSET(int fd, fd_set *set);//  Determine file descriptors fd Whether in set Collection  ==  Read it fd The corresponding flag bit is 0 still 1
void FD_SET(int fd, fd_set *set);//  File descriptors fd Add to set Collection  ==  take fd The corresponding flag bit is set to 1
void FD_ZERO(fd_set *set);     // take set Collection ,  The flag bit corresponding to all file descriptors is set to 0,  No file descriptors were added to the collection 

Example use process

The previous preparations remain unchanged ,socket()->bind()->listen()

int lfd, cfd;
    socklen_t client_len;
    char buff[MAXLEN];
    struct sockaddr_in serv_addr, client_addr;
    memset(&serv_addr, 0, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(SERV_PORT);
    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);

    lfd = socket(AF_INET, SOCK_STREAM, 0);
    if (lfd == -1)
        perr_exit("socket error ");

    if (bind(lfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) == -1)
        perr_exit("bind error");

    if (listen(lfd, 128) == -1)
        perr_exit("listen error");

To set a variable that traverses the maximum file descriptor , To update , The maximum upper limit of traversal , The initial size is set to socked The size of the file descriptor being listened to is sufficient

int maxfd = lfd;

Create two fd_set Type of the array , For storing and traversing , Because the internal parameters may be changed during traversal, create one to be used as another copy , Complete initialization and add listening events

FD_ZERO(&redset);
FD_SET(lfd, &redset); // What will be monitored lfd Set to the detected read set 

The following process has been fully annotated later

 while (1)
    {
    
        tmp = redset; // Create copy 
        int cnt = select(maxfd + 1, &tmp, NULL, NULL, NULL);// Indicates the maximum value of the file descriptor that needs to be monitored  + 1, In fact, it is essentially a linear table in order to listen to the last file descriptor, so +1;
        if (cnt < 0)
            perr_exit("select error");

        if (FD_ISSET(lfd, &tmp)) // Judge whether it is monitored lfd, Is there a new client initiating the connection 
        {
    
            cfd = accept(lfd, (struct sockaddr *)&client_addr, &client_len); // Monitor client , Establish a connection with the requesting client 
            if (cfd == -1)
                perr_exit("accept error");
    
            FD_SET(cfd, &redset);// Add to the original array 
            maxfd = cfd > maxfd ? cfd : maxfd;// Judge  maxfd Is it the current maximum limit 
        }

        for (int j = lfd + 1; j <= maxfd; ++j)    // j from lfd The next step is to start 
        {
    
            if (FD_ISSET(j, &tmp)) //  Receive data 
            {
    
                int ret = read(j, buff, sizeof(buff));
                if (ret == -1)
                    perr_exit("read error");
                else if (ret == 0)
                {
    
                    printf(" client close ----\n"); // The client of this communication has been closed 
                    FD_CLR(j, &redset);             // Move it out of the collection 
                    close(j);
                }
                else
                {
    
                    for (int i = 0; i < ret; i++)
                        buff[i] = toupper(buff[i]);
                    ret = write(j, buff, ret);
                    if (ret == -1)
                        perr_exit("wirte error");
                    write(STDOUT_FILENO, buff, ret);
                }
            }
        }
    }
原网站

版权声明
本文为[Gy648]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/160/202206092118511078.html