select of linux Multiplexing

1. select function
1. Definition
select: This function allows a process to instruct the kernel to wait for any one of multiple events to occur and to wake it up only after one or more events have occurred or experienced a specified period of time.
2. Role
(1) The system provides select function to realize multiplexing input/output model.
(2) select system calls are used to allow our program to monitor the state changes of multiple file handles.
3. Interface parameters

FD_CLR(inr fd,fd_set* set); used to clear the position of related FD in the set of descriptive phrases

FD_ISSET (int fd, fd_set*set); used to test whether the bits of the relevant FD in the description phrase set are true

FD_SET (int fd,fd_set*set); used to set the bits of the relevant FD in the description phrase set

FD_ZERO (fd_set*set); used to remove all parts of the descriptive phrase set

(1) nfds: Number of descriptors to be tested. Maximum file descriptor + 1.

(2) readfds: a set of readable file descriptors that need to be detected.

(3) writefds: Writable file descriptor set.

(4) exceptfds: Exception file descriptor set. (There are two reasons for the exception: 1. the arrival of out-of-band data for a socket; 2. the presence of control status information that can be read from the main terminal of a pseudo-terminal that has been set in grouping mode)

(5) timeout: It tells the kernel how long it can wait for any of the specified descriptors to be ready, and its timeval structure is used to specify the number of seconds and subtleties for that period.

struct timeval
{
    long tv_sec;//seconds
    long tv_usec;//microseconds
}

Wait forever (* timeout = NULL):
Returns only when one descriptor is ready for I/O.

(2) Time out - > tv_sec! = 0 & timeout - > tv_usec! = 0:
Returns when a descriptor is ready for I/O, but does not exceed the number of seconds and subtleties specified in the timeval structure to which the parameter refers.

(3) No waiting at all (timeout - > tv_sec == 0 & & timeout - > tv_usec == 0): Check the descriptor and return immediately, which is called polling.

In the first two cases, the waiting is usually interrupted by the signal captured by the process during the waiting period and returned from the signal processing function.
4. Advantages and disadvantages
Advantages: Compared with multi-process/thread, it shortens waiting time, improves efficiency and reduces process memory overhead.

Disadvantages:
(1) Each call to select requires copying the FD set from the user state to the kernel state, which costs a lot in fd.
(2) At the same time, every call to select needs to traverse all FDS passed in by the kernel, which costs a lot in many fd s.
(3) The number of file descriptors supported by select is too small. The default is 1024.
II. dup
(1) Definition
dup: Used to copy the file descriptor referred to by oldfd. But when the copy is successful, the smallest unused file descriptor is returned. If there is an error, return - 1, and the error code is stored in errno. The returned new file descriptor and parameter oldfd point to the same file, sharing all locks, read and write pointers, and permissions or flags.

(2) Actual operation
1. Open a new file

2. Turn off the standard output file characters

3. Call dup to the file descriptor

4. At this point, the file descriptor becomes 1

5. redirect the data to be printed to a file

III. Code
1.sever end

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

    int array_fds[1024];  

    static void Usage(char* proc)  
    {  
        printf("Usage: %s [local_ip] [local_port]", proc);  
    }  

    int startup(char* _ip, int _port)  
    {  
        int sock = socket(AF_INET, SOCK_STREAM, 0);  
        if(sock < 0)  
        {  
            perror("socket");  
            return 2;  
        }  

        int flg = 1;  
        setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &flg, sizeof(flg));  

        struct sockaddr_in local;  
        local.sin_family = AF_INET;  
        local.sin_port = htons(_port);  
        local.sin_addr.s_addr = inet_addr(_ip);  

        if(bind(sock, (struct sockaddr*)&local, sizeof(local)) < 0)  
        {  
            perror("bind");  
            return 3;  
        }  

        if(listen(sock, 5) < 0)  
        {  
            perror("listen");  
            return 0;  
        }  
        return sock;  
    }  

    int main(int argc, char* argv[])  
    {  
        if(argc != 3)  
        {  
            Usage(argv[0]);  
            return 1;  
        }  

        int listen_socket = startup(argv[1], atoi(argv[2]));  

        fd_set rfds;  
        int max_fd = 0;  
        int array_size = sizeof(array_fds)/sizeof(array_fds[0]);  
        array_fds[0] = listen_socket;  
        int i = 0;  
        for(i = 1; i < array_size; i++)  
        {  
            array_fds[i] = -1;  
        }  
        while(1)  
        {  
            max_fd = -1;  
            struct timeval timeout = {0,0};  
            FD_ZERO(&rfds);  
            for(i = 0; i < array_size; i++)  
            {  
                if(array_fds[i] > 0)  
                {  
                    FD_SET(array_fds[i], &rfds);  
                    if(array_fds[i] > max_fd)  
                    {  
                        max_fd = array_fds[i];  

                    }  
                }  
            }  

            switch(select(max_fd+1, &rfds, NULL,NULL, NULL))  
            {  
                case 0:  
                    printf("timeout...\n");  
                    break;   
                case -1:  
                    perror("select");  
                    break;   
                default:  
                    {   

                        int k = 0;  
                        for(;k < array_size; k++)  
                        {  
                            if(array_fds[k] < 0)  
                                continue;  

                            if(k == 0 && FD_ISSET(array_fds[k], &rfds))  
                            {  

                                struct sockaddr_in client;  
                                socklen_t len = sizeof(client);  
                                int new_sock = accept(array_fds[k], (struct sockaddr*)&client, &len);  
                                if(new_sock < 0)  
                                {  
                                    perror("accept");  
                                    continue;   
                                }  
                                else  
                                {  
                                    printf("get a client : %s ,  %d \n", inet_ntoa(client.sin_addr), ntohs(client.sin_port));  
                                    int j = 1;  
                                    for(;j < array_size;j++)  
                                    {  
                                        if(array_fds[j] < 0)    
                                        {  
                                            array_fds[j] = new_sock;  
                                            break;  
                                        }  
                                    }  
                                    if(j == array_size)  
                                        close(new_sock);  

                                }  
                            }  
                            else if(k != 0 && FD_ISSET(array_fds[k],&rfds))  
                            {  

                                char buf[10240];  
                                ssize_t s = read(array_fds[k], buf, sizeof(buf)-1);  
                                if(s > 0)  
                                {  
                                    buf[s] = 0;   
                                    printf("client say# %s \n", buf);  
                                    write(array_fds[k], buf, strlen(buf));  
                                }  
                                else if(s == 0)  
                                {  
                                    printf("client quit ...\n");  
                                    close(array_fds[k]);  
                                    array_fds[k] = -1;  
                                }  
                                else  
                                {  
                                    perror("read");  
                                    close(array_fds[k]);  
                                    array_fds[k] = -1;  
                                }    
                            }  
                            else  
                            {  
                            }  
                         }   

                    }  
                    break;   
            }  
        }  
        return 0;  
    }  

2.client end

    #include<stdio.h>  
    #include<sys/types.h>  
    #include<netinet/in.h>  
    #include<arpa/inet.h>  
    #include<sys/socket.h>  
    #include<stdlib.h>  
    #include<string.h>  
    #include<strings.h>  
    #include<sys/stat.h>  
    #include<unistd.h>  
    static void Usage(char * proc)  
    {  
        printf("Usage : %s [ip] [port]\n");  
    }  

    int main(int argc, char* argv[])  
    {  
        if(argc != 3)  
        {  
            Usage(argv[0]);  
            return 1;  
        }  

        int sock = socket(AF_INET, SOCK_STREAM, 0);  
        struct sockaddr_in peer;  
        peer.sin_family = AF_INET;  
        peer.sin_port = htons(atoi(argv[2]));  
        peer.sin_addr.s_addr = inet_addr(argv[1]);  

        if(connect(sock, (struct sockaddr*)&peer, sizeof(peer)) < 0)  
        {  
            perror("connect");  
            return 2;  
        }  

        char buf[10240];  

        while(1)  
        {  
            printf("Please Enter : ");  
            fflush(stdout);  
            ssize_t s = read(0, buf, sizeof(buf)-1);  
            int sfd = dup(STDOUT_FILENO);  
            if(s > 0)  
            {  
                buf[s-1] = 0;  

               int new_fd = dup2(sock, 1);  
                if(new_fd == -1)  
                {  
                   perror("dup()");  
                   return -1;  
                }  
                printf("%s",buf);  
                fflush(stdout);  

                dup2(sfd, STDOUT_FILENO);  

                ssize_t _s = read(sock, buf, sizeof(buf)-1);  
                if(_s > 0)  
                {  
                   buf[_s] = 0;  
                   printf("sever # %s \n", buf);  
                }  
            }  
        }  
        close(sock);  
        return 0;  
    }  

Keywords: socket

Added by btrsrinivasarao on Mon, 24 Jun 2019 02:23:12 +0300