The Select function describes:
intSelect (intMaxfdp,fd_set*Readfds,fd_set*Writefds,fd_set*Errorfds,structTimeval*timeout); /*The argument list int MAXFDP is an integer value that refers to the range of all file descriptors in the collection, that is, the maximum value of all file descriptors plus 1, not wrong! The value of this parameter in Windows does not matter and can be set incorrectly. Fd_set *readfds is a pointer to the FD_SET structure, which should include the file descriptor, we want to monitor the read changes of these file descriptors, that is, we care whether the data can be read from these files, if there is a file in this collection is readable, Select returns a value greater than 0, indicating that the file is readable, and if there is no readable file, the timeout parameter is used to determine whether to time out, and if timeout is exceeded, select returns 0 if an error returns a negative value. You can pass in a null value to indicate that you do not care about any file read changes. Fd_set *writefds is a pointer to the FD_SET structure, which should include the file descriptor, we want to monitor the write changes of these file descriptors, that is, we care about whether the data can be written to these files, if there is a file in this collection can be written, Select returns a value greater than 0, indicating that a file is writable, and if there is no writable file, the timeout parameter is used to determine whether to time out, and if timeout is exceeded, select returns 0 if an error returns a negative value. You can pass in a null value to indicate that you do not care about any file write changes. Fd_set *errorfds with the above two parameters to monitor file error exceptions. The struct timeval* timeout is the time-out for Select, which is critical, which allows the select to be in three states: first, if NULL is passed in as a parameter, that is, the time structure is not passed in, the select is put in a blocking state. Be sure to wait until one of the file descriptors in the monitor file descriptor collection changes; second, if the time value is set to 0 seconds 0 milliseconds, it becomes a purely non-blocking function, regardless of whether the file descriptor is changed, immediately return to continue execution, the file has no change return 0, there is a change to return a positive value; Timeout value is greater than 0, this is the waiting time-out period, that is, select in timeout time block, the timeout period has the arrival of the event to return, otherwise after the timeout, anyway must return, the return value with the above. */
/* return value:
Negative value: Select Error positive value: Some files can be read or write or error 0: Wait timeout, no writable or incorrect files */
Specific implementation code comments I would like to detail: Server side
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <errno.h> #include < string.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include < Arpa/inet.h> #define MYPORT 8000//The port users would be a connecting to#define max_connet 5//How many pending Connections queue would hold#define buf_size 200int fd_a[max_connet]; Accepted connection Fdint Conn_amount; Current Connection Amountvoid showclient () {int i; printf ("Client Amount:%d\n", Conn_amount); for (i = 0; i < max_connet; i++) {printf ("[%d]:%d", I, fd_a[i]); } printf ("\ n");} int main (void) {int sock_fd, NEW_FD; Listen on SOCK_FD, new connection on new_fd struct sockaddr_in server_addr; Server address information struct sockaddr_in client_addr; Connector ' s address information socklen_t sin_size; Socklen_t, which is a bit like int, is used to denote the length int yes = 1; Char Buf[buf_size]; int ret; int i; if (SOCK_FD = socket (af_inet, sock_stream, 0)) = =-1) {perror ("socket"); Exit (1); } if (setsockopt (SOCK_FD, Sol_socket, so_reuseaddr, &yes, sizeof (int)) = =-1) {perror ("setsockopt"); Exit (1); } server_addr.sin_family = Af_inet; Host byte order Server_addr.sin_port = Htons (MyPort); Short, network byte order server_addr.sin_addr.s_addr = Inaddr_any; Automatically fill with my IP memset (Server_addr.sin_zero, ' + ', sizeof (Server_addr.sin_zero)); if (Bind (SOCK_FD, (struct sockaddr *) &server_addr, sizeof (SERVER_ADDR)) = =-1) {perror ("bind"); Exit (1); } if (Listen (SOCK_FD, max_connet) = =-1) {perror ("listen"); Exit (1); } printf ("Listen Port%d\n", MyPort); Fd_set FDSR; int maxsock; struct Timeval TV; Conn_amount = 0; sin_size = sizeof (CLIENT_ADDR); Maxsock = SOCK_FD; while (1) {//Initialize File descriptor set Fd_zero (&FDSR); Fd_set (SOCK_FD, &FDSR); Timeout setting tv.tv_sec = 30; tv.tv_usec = 0; Add active connection to FD set for (i = 0; i < max_connet; i++) {if (fd_a[i]! = 0) { Fd_set (Fd_a[i], &FDSR); }} ret = select (Maxsock + 1, &FDSR, NULL, NULL, &TV); if (Ret < 0) {perror ("select"); Break } else if (ret = = 0) {printf ("timeout\n"); printf ("Client numbers:%d\n", Conn_amount); Continue }//Check every FD in the set for (i = 0; i < Conn_amount; i++) {if (Fd_isset (Fd_a[i], & FDSR) {ret = recv (Fd_a[i], buf, sizeof (BUF), 0); if (ret <= 0) {//Client close printf ("client[%d] close\n", i); Close (Fd_a[i]); FD_CLR (Fd_a[i], &FDSR); Fd_a[i] = 0; conn_amount--; Reduce the number of client connections} else {//Receive data if (Ret < buf_size) memset (&buf[ret], ' n ', 1); printf ("client[%d] send:%s\n", I, buf); Send to Cilent if (send (Fd_a[i], "Hello is connected!\n", 0) = =-1) {perror ("send Error"); Close (fd_a[i ]); FD_CLR (Fd_a[i], &FDSR); fd_a[i] = 0;conn_amount--; }}}}//Check whether a new connection comes if (Fd_isset (SOCK_FD, & AMP;FDSR) {new_fd = Accept (sock_fd, (struct sockaddr *) &client_addr, &sin_size); if (new_fd <= 0) {perror ("accept"); Continue }//Add to FD queue if (Conn_amount < max_connet) {fd_a[conn_amount++] = NEW_FD; /*for (i = 0; i < max_connet; i++) {if (fd_a[i] = = 0)//find seat to add new fd{fd_a[i] = NEW_FD;}} */conn_amount++; printf ("New connection client[%d]%s:%d\n", Conn_amount, Inet_ntoa (CLIENT_ADDR.SIN_ADDR), Ntohs (CLI Ent_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); Break }} showclient (); }//Close other connections for (i = 0; i < max_connet; i++) {if (fd_a[i]! = 0) {Close (fd_a[ I]); }} exit (0);}
Client side:
/* File name:client.c */#include <stdio.h> #include <stdlib.h> #include <STRING.H&G T #include <errno.h> #include <sys/types.h> #include <sys/socket.h> #include <NETINET/IN.H&G T #define MAXLINE 4096 int main (int argc, char** argv) {int sockfd, N,rec_len; Char recvline[4096], sendline[4096]; Char Buf[maxline]; struct sockaddr_in servaddr; if (argc! = 2) {printf ("Usage:./client <ipaddress>\n"); Exit (0); } if ((SOCKFD = socket (af_inet, sock_stream, 0)) < 0) {printf ("Create Socket Error:%s (er Rno:%d) \ n ", Strerror (errno), errno); Exit (0); } memset (&servaddr, 0, sizeof (SERVADDR)); servaddr.sin_family = af_inet; Servaddr.sin_port = htons (8000); if (Inet_pton (Af_inet, argv[1], & servaddr.sin_addr) <= 0) {printf ("Inet_pton error for%s\n", argv[1]); Exit (0); } if (Connect (SOCKFD, (struct sockaddr*) &servaddr, sizeof (SERVADDR)) < 0) {printf ("Co Nnect Error:%s (errno:%d) \ n ", Strerror (errno), errno); Exit (0); } printf ("Send msg to server: \ n"); Fgets (Sendline, 4096, stdin); if (Send (SOCKFD, Sendline, strlen (Sendline), 0) < 0) {printf ("Send msg Error:%s (errno:%d) \ n", stre Rror (errno), errno); Exit (0); } if ((Rec_len = recv (SOCKFD, buf, maxline,0)) = =-1) {perror ("recv error"); Exit (1); } Buf[rec_len] = ' + '; printf ("Received:%s", buf); Close (SOCKFD); Exit (1); }
Select-based socket communication under Linux