Select-I/O multiplexing

Source: Internet
Author: User

Socket using the select function
What if you want to keep the existing connection while listening for new connections?
Common Practice (you cannot use recv or accept ). When the accetp is used to wait for a new connection, the program is blocked and there is no way to maintain communication with the original connection.
Another way is to use the non-blocking method, but this will waste valuable CPU time (your non-stop round robin ).
Is there a better way? The answer is yes-use the select function.
Select can help you monitor multiple sockets at the same time. It tells you which socket is ready to read data, which socket is ready to write data, and which socket has an error.
Using select means I/O multiplexing.

Select function header file:
# Include <sys/time. h>
# Include <sys/types. h>
# Include <unistd. h>

Select function prototype:
Int select (int numfds, fd_set * readfds, fd_set * writefds, fd_set * limit TFDs, struct timeval * timeout );
For more information, see man select
Parameters of the select () function:
Numfds is the maximum number in the file descriptor of the fd set in readfds, writefds, and limit TFDs plus 1.
The fd set in readfds is monitored by select to determine whether data can be read.
The fds set in writefds will be monitored by select to determine whether data can be written.
The fds set in exceptfds will be monitored by select to see if exceptions occur.
Timeout is used to set the wait timeout.
Return Value:
If successful, the number of ready file descriptors is returned. Generally, 0 is returned for timeout. -1 is returned.
The timeval structure is defined as follows:
Struct timeval
{
Int TV _sec;/* seconds */
Int TV _usec;/* microseconds */
};
You only need to set TV _sec to the number of seconds you want to wait, and then set TV _usec to the number of microseconds you want to wait (true
The time is the number of seconds in TV _sec plus the number of microseconds in TV _usec ). When the select () function returns, the time in timeval will be set to the remaining time after the select () function is executed.

If you want to know whether data can be read from standard input and some sockets (sockfd), you can add the file descriptor and sockfd to readfds. The numfds value is set to add the largest one in the file descriptor in readfds, that is, sockfd + 1 (because the value of the standard input file descriptor is 0, so any other file descriptor will be larger than the standard input file descriptor ).
When the select () function returns, readfds will be modified to tell you which file descriptor you can use to read data. Using the FD_ISSET () Macro, you can select the execution result of the select () function.

Process the fd_set macro:
FD_ZERO (fd_set * set) clears a file descriptor set
FD_SET (int fd, fd_set * set) adds the file descriptor fd to the set-so that select will listen to its status.
FD_CLR (int fd, fd_set * set) removes the file descriptor fd from the set. select no longer listens to its status.
FD_ISSET (int fd, fd_set * set) checks whether the status of fd in the fdset set changes. True is returned when the fd status is detected to change. Otherwise, false is returned.

The following program waits for the input data from the standard input and prints the input data. If no input is made within 3 seconds (input is considered as input ready), the print times out or an error occurs.

View Code

#include <sys/time.h>#include <unistd.h>#include <sys/types.h>#include <stdio.h>int main(int argc, char **argv){    fd_set fdsets;    FD_ZERO(&fdsets);    FD_SET(STDIN_FILENO, &fdsets);    struct timeval timeout;    timeout.tv_sec = 5;    timeout.tv_usec = 0;    char buff[50];    if (select(2, &fdsets, NULL, NULL, &timeout)>0)    {        if (FD_ISSET(STDIN_FILENO, &fdsets))        {                scanf("%s", buff);                printf("has input\n");        }    }    else    {        printf("timeout or error!\n");    }    return 0;}        

The following example uses select to listen to multiple connections at the same time:

View Code

# Include <sys/types. h> # include <sys/socket. h> # include <netinet/in. h> # include <arpa/inet. h> # include <unistd. h> # define PORT 1234 # define MAXSOCKFD 10int main (int argc, char ** argv) {int sockfd, newsockfd, is_connected [MAXSOCKFD], fd; struct sockaddr_in addr; int addr_len = sizeof (struct sockaddr_in); fd_set readfds; char buffer [256]; char msg [] = "Welcome to server! "; If (sockfd = socket (AF_INET, SOCK_STREAM, 0) <0) {perror (" socket "); exit (1);} bzero (& addr, sizeof (addr); addr. sin_family = AF_INET; addr. sin_port = htons (PORT); addr. sin_addr.s_addr = htonl (INADDR_ANY); if (bind (sockfd, & addr, sizeof (addr) <0) {perror ("connect"); exit (1 );} if (listen (sockfd, 3) <0) {perror ("listen"); exit (1) ;}for (fd = 0; fd <MAXSOCKFD; fd ++) is_connected [fd] = 0; while (1) {FD_ZERO (& rea Dfds); FD_SET (sockfd, & readfds); // used to listen for new connections (fd = 0; fd <MAXSOCKFD; fd ++) {if (is_connected [fd]) FD_SET (fd, & readfds); // added the select listener to the processed connection} if (! Select (MAXSOCKFD, & readfds, NULL) continue; for (fd = 0; fd <MAXSOCKFD; fd ++) {if (FD_ISSET (fd, & readfds) {if (sockfd = fd) // an unprocessed connection {if (newsockfd = accept (sockfd, & addr, & addr_len) <0) perror ("accept"); write (newsockfd, msg, sizeof (msg); is_connected [newsockfd] = 1; printf ("cnnect from % s \ n ", inet_ntoa (addr. sin_addr);} else // The processed connections are read ready {bzero (buffer, sizeof (buffer); if (read (fd, buffer, sizeof (buffer )) <= 0) // Data Reading failed, indicating that the connection is closed {printf ("connect closed. \ n "); is_connected [fd] = 0; close (fd) ;}else // successfully read data printf (" % s ", buffer );}}}}}

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.