Function declaration select function
Int select (INT NFDs, fd_set * readfds, fd_set * writefds, fd_set * limit TFDs, struct timeval * timeout );
Note:
Int maxfdp is an integer that indicates the range of all file descriptors in the collection, that is, the maximum value of all file descriptors plus 1.
Fd_set * readfds is a pointer to the fd_set structure. This collection should contain file descriptors. We want to monitor the read changes of these file descriptors, that is, we are concerned about whether data can be read from these files. If a file in this collection is readable, select returns a value greater than 0, indicating that the file is readable, if there is no readable file, the timeout parameter is used to determine whether to time out. If the time exceeds the timeout time, select returns 0. If an error occurs, a negative value is returned. You can pass in a null value, indicating that you do not care about any file read changes.
Fd_set * writefds is a pointer to the fd_set structure. This collection should contain file descriptors. We want to monitor the write changes of these file descriptors, that is, we are concerned about whether data can be written to these files. If there is a file in this collection that can be written, select will return a value greater than 0, indicating that a file is writable, if no writable file exists, the timeout parameter is used to determine whether to time out. If the time exceeds the timeout time, select returns 0. If an error occurs, a negative value is returned. You can pass in a null value, indicating that you do not care about any file write changes.
Fd_set * errorfds indicates the intention of the two parameters above, which is used to monitor file error exceptions.
Struct timeval * timeout is the select timeout time. This parameter is crucial. It can make the select statement in three States. First, if NULL is input as an input parameter, that is, the time structure is not input, that is, the select statement is placed in the blocking state. It must wait until a file descriptor in the collection of monitored file descriptors changes. Second, if the time value is set to 0 s and 0 ms, it becomes a pure non-blocking function. no matter whether the file descriptor has changed or not, it immediately returns to continue execution. If the file does not change, 0 is returned, and a positive value is returned. Third, the value of timeout is greater than 0, this is the waiting timeout time, that is, the select statement is blocked within the timeout time, and an event will be returned within the time-out time. Otherwise, no matter how long it will be returned, the return value is the same as the above.
Return Value:
Negative value: select error positive value: some files can be read or written, or errors 0: wait for timeout, there is no readable or wrong file
With select, you can write a decent network program! A simple example is to accept data from the network and write it into a file.
Description socket read/write conditions:
When either of the following four conditions is met, the set interface is ready to read:
(1) The number of data bytes in the interface receiving buffer is greater than or equal to the current value in the interface receiving buffer. You can use SO_REVILOAT to set this low tide limit.
(2) The read half of the connection is closed, that is, the TCP connection that receives the FIN is closed,
(3) the set of interfaces is a set of listening interfaces and the number of established connections is not 0.
(4) There is an interface for handling errors.
When either of the following three conditions is met, the set interface is ready to write:
(1) the available space byte of the interface sending buffer is greater than or equal to the current value at the low tide of the interface sending buffer, or (I) the interface is connected, or (ii) connection is not required for the set of interfaces.
(2) The write half of the connection is closed, and the write operation on such an interface will generate a signal SIGPIEP.
(3) There is a set of interface errors to be processed.
Descriptor set
Fd_zero (fd_set * fdset): clears the contact between fdset and all file handles.
Fd_set (int fd, fd_set * fdset): Establishes the connection between the file handle FD and fdset.
Fd_clr (int fd, fd_set * fdset): clears the contact between the file handle FD and fdset.
Fd_isset (int fd, fdset * fdset): Check whether the file handle FD associated with fdset is readable or not.> 0 indicates that the file handle FD can be read or written.
Code example (reproduced)
Reprinted from click to open the link
Server
/* Use the select function to communicate with multiple sockets in a non-blocking manner. The program only demonstrates the use of the select function. Even if a connection is closed, the current number of connections is not modified. After the maximum number of connections is reached, the program is terminated. 1. The program uses an array FD. After the communication starts, multiple socket descriptors to be communicated are put in this array. 2. A socket descriptor named sock_fd is generated first for listening to the port. 3. Put the descriptor not 0 in sock_fd and array FD into the fdsr set to be checked by select. 4. Processes connections that can receive data in fdsr. For sock_fd, a new connection is added, and the socket descriptor of the new connection is placed in FD. * /// Select_server.c # include <stdio. h> # include <stdlib. h> # include <unistd. h> # include <errno. h> # include <string. h> # include <sys/types. h> # include <sys/socket. h> # include <sys/time. h> # include <netinet/in. h> # include <ARPA/inet. h> # define myport 1234 // port used during connection # define maxcline 5 // Number of connections in the queue # define buf_size 200int FD [maxcline]; // connection fdint conn_amount; // The number of current connections void showclient () {int I; printf ("client amount: % D \ n ", conn_amount); for (I = 0; I <maxcline; I ++) {printf (" [% d]: % d ", I, FD [I]);} printf ("\ n");} int main (void) {int sock_fd, new_fd; // listen to the socket connection socket struct sockaddr_in server_addr; // The server address information struct sockaddr_in client_addr; // The client address information socklen_t sin_size; int Yes = 1; char Buf [buf_size]; int ret; int I; // create a sock_fd socket If (sock_fd = socket (af_inet, sock_stream, 0) =-1) {perror ("setsockopt"); exit (1 );} // set so_reuseaddr. Allow the second parameter Sol socket of multiple instances // setsockopt of the server to be started on the same port to specify the system, and explain the option-level common socket If (setsockopt (sock_fd, sol_socket, so_reuseaddr, & yes, sizeof (INT) =-1) {perror ("setsockopt error \ n"); exit (1) ;}server_addr.sin_family = af_inet; // host byte sequence = htons (myport); Sequence = inaddr_any; // wildcard ipmemset (server_addr.sin_zero, '\ 0', sizeof (server_addr.sin_zero); If (BIND (sock_fd, (struct sockaddr *)& Server_addr, sizeof (server_addr) =-1) {perror ("BIND error! \ N "); exit (1);} If (Listen (sock_fd, maxcline) =-1) {perror (" Listen error! \ N "); exit (1) ;}printf (" Listen port % d \ n ", myport); fd_set fdsr; // defines int maxsock for the file descriptor set; struct timeval TV; conn_amount = 0; sin_size = sizeof (client_addr); maxsock = sock_fd; while (1) {// initialize the file descriptor set fd_zero (& fdsr ); // clear the descriptor set fd_set (sock_fd, & fdsr); // Add sock_fd to the descriptor set // timeout setting TV. TV _sec = 30; TV. TV _usec = 0; // Add an active connection for (I = 0; I <maxcline; I ++) {If (FD [I]! = 0) {fd_set (FD [I], & fdsr) ;}// if there is a connection request in the file descriptor, it will be processed accordingly, achieve I/O multiplexing multi-user connection communication ret = select (maxsock + 1, & fdsr, null, null, & TV); If (Ret <0) // no valid connection found {perror ("select error! \ N "); break;} else if (ret = 0) // specifies the time, {printf (" timeout \ n "); continue ;} // cyclically determine whether data in a valid connection reaches for (I = 0; I <conn_amount; I ++) {If (fd_isset (FD [I], & fdsr )) {ret = Recv (FD [I], Buf, sizeof (BUF), 0); If (Ret <= 0) // The client connection is closed, clear the corresponding bits in the file descriptor set {printf ("client [% d] Close \ n", I); close (FD [I]); fd_clr (FD [I], & fdsr); FD [I] = 0; conn_amount --;} // otherwise, data is sent and processed accordingly. else {If (Ret <buf_size) memset (& Buf [RET], '\ 0', 1); printf ("client [% d] Send: % s \ n ", I, Buf) ;}}}if (fd_isset (sock_fd, & fdsr) {new_fd = accept (sock_fd, (struct sockaddr *) & client_addr, & sin_size ); if (new_fd <= 0) {perror ("Accept error \ n"); continue;} // Add a new FD to the array to determine whether the valid number of connections is less than the maximum number of connections, if the value is less than, add the new connection socket to the set if (conn_amount <maxcline) {for (I = 0; I <maxcline; I ++) {If (FD [I] = 0) {FD [I] = new_fd; break;} conn_amount ++; printf ("New Connection Client [% d] % s: % d \ n ", conn_amount, inet_ntoa (client_addr.sin_addr), ntohs (Client_addr.sin_port); If (new_fd> maxsock) {maxsock = new_fd ;}} else {printf ("Max connections arrive, exit \ n"); send (new_fd, "bye", 4,0); close (new_fd); Continue ;}} showclient () ;}for (I = 0; I <maxcline; I ++) {If (FD [I]! = 0) {close (FD [I]) ;}} exit (0 );}Client
// A simple implementation of the client, just to verify the correctness of the server program // select_client.c # include <stdio. h> # include <stdlib. h> # include <errno. h> # include <string. h> # include <netdb. h> # include <sys/types. h> # include <netinet/in. h> # include <sys/socket. h> # include <sys/types. h> # define MAXDATASIZE 100 # define SERVPORT 1234 # define MAXLINE 1024int main (int argc, char * argv []) {int sockfd, sendbytes; // char send [MAXLINE]; char send [MAXLINE]; char buf [MA XDATASIZE]; struct hostent * host; struct sockaddr_in serv_addr; if (argc <2) {fprintf (stderr, "Please enter the server's hostname \ n "); exit (1);} if (host = gethostbyname (argv [1]) = NULL) {perror ("gethostbyname"); exit (1 );} if (sockfd = socket (AF_INET, SOCK_STREAM, 0) =-1) {perror ("socket error \ n"); exit (1);} serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons (SERVPORT); serv_addr.sin_addr = * (struct I N_addr *) host-> h_addr); bzero (& (serv_addr.sin_zero), 8); if (connect (sockfd, (struct sockaddr *) & serv_addr, sizeof (struct sockaddr )) =-1) {perror ("connect \ n"); exit (1) ;}while (fgets (send, 1024, stdin )! = NULL) {if (sendbytes = write (sockfd, send, 100) =-1) {perror ("send error \ n "); exit (1) ;}} close (sockfd );}