Select for socket communication
Many users use single-thread communication for socket communication. At the same time, you can only listen to one port and only respond to one service. The select method can solve the problem of multiple sockets being connected. Multiple resources can be allocated at a time, and only one connection can be used for communication. There are already many select examples in the network. However, many examples do not really reflect the subtlety of select. This function Monitors multiple file descriptors until one or more file descriptors are connected.
First, we will introduce the fd_set structure:
Fd_set can be understood as a collection in which the file descriptor (file descriptor) is stored, that is, the file handle. This can be what we call a common object, of course, any device, pipeline, and FIFO in Unix are all in the file format, so there is no doubt that a socket is a file, and a socket handle is a file descriptor. The fd_set set can be operated manually by some macros, such as clearing the set FD_ZERO (fd_set *) and adding a given file descriptor to the set FD_SET (int, fd_set *), deletes a given file descriptor from the collection FD_CLR (int, fd_set *).
Before using this structure in select, we need to call FD_SET to set the flag of the corresponding socket. This is where many network errors occur, it is necessary to bind multiple sockets to realize the select multi-fd listener. You cannot specify it at will, for example, FD_SET (0, XX). This type of fd is actually occupied by the system. After the select statement is returned successfully, check whether the specified file descriptor in the set can read and write FD_ISSET (int, fd_set *). Then, read and write operations are performed based on the corresponding fd. Paste the Code directly:
1 # include <iostream> 2 # include <sys/times. h> 3 # include <sys/types. h> 4 # include <unistd. h> 5 # include <sys/socket. h> 6 # include <sys/select. h> 7 # include <cstdlib> 8 # include <cstdio> 9 # include <cstring> 10 # include <string> 11 # include <signal. h> 12 # include <netinet/in. h> 13 # include <arpa/inet. h> 14 # include <errno. h> 15 using namespace std; 16 17 # define max (a, B) (a)> (B )? (A) :( B) 18 19 static int listen_socket (int port) 20 {21 sockaddr_in s_in; 22 int s; 23 int yes; 24 if (s = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP) =-1) 25 {26 cout <"socket error" <strerror (errno) <endl; 27 return-1; 28} 29 yes = 1; 30 if (setsockopt (s, SOL_SOCKET, SO_REUSEADDR, (char *) & yes, sizeof (yes) =-1) 31 {32 cout <"setsockopt error" <strerror (errno) <endl; 33 close (s); 34 return -1; 35} 36 37 memset (& s_in, 0, sizeof (s_in); 38 s_in.sin_port = htons (port); 39 s_in.sin_family = AF_INET; 40 s_in.sin_addr.s_addr = inet_addr ("127.0.0.1"); 41 if (bind (s, (sockaddr *) & s_in, sizeof (s_in) =-1) 42 {43 cout <"bind error" <strerror (errno) <endl; 44 close (s); 45 return-1; 46} 47 listen (s, 10); 48 cout <"socket-> setsockopt-> bind-> listen" <port <endl; 49 return s; 50} 51 52 53 54 Int main (int argi, char * args []) 55 {56 int h, h1; 57 int fd1 =-1, fd2 =-2; 58 59 if (argi! = 3) 60 {61 cout <"Usage server listen_port1 listen_port2" <endl; 62 exit (-1 ); 63 64} 65 66 int listen_port1 = atoi (args [1]); 67 fd1 = listen_socket (listen_port1); 68 int listen_port2 = atoi (args [2]); 69 fd2 = listen_socket (listen_port2); // two sockets are created here: cy1_dm0503 70 if (fd1 =-1 | fd2 =-1) 71 {72 exit (-1); 73} 74 for (;) 75 {76 int r, nfds = 0; 77 fd_set rfd, sfd; 78 79 FD_ZERO (& rfd); 80 FD_ZE RO (& sfd); 81 FD_SET (fd1, & rfd); // bind two socket 82 FD_SET (fd2, & rfd); 83 84 int maxnum = max (6, fd1); 85 maxnum = max (fd2, maxnum); 86 cout <"maxnum:" <maxnum <"\ t"
When the select statement listens to the rfd set of the corresponding socket, if a corresponding client links one of the two sockets, the select edge can return the corresponding information, and then calls FD_ISSET, obtain the connected socket, perform accept, and send and receive information.
The following is the sample code of the client:
1 #include <iostream> 2 #include <sys/socket.h> 3 #include <unistd.h> 4 #include <sys/types.h> 5 #include <netdb.h> 6 #include <cstdio> 7 #include <cstdlib> 8 #include <cstring> 9 #include <string>10 #include <iostream>11 #include <netinet/in.h>12 #include <arpa/inet.h>13 #include <errno.h>14 15 using namespace std;16 17 int main(int argi, char* args[])18 {19 if( argi<3)20 {21 cout<<args[0]<<"\t"<<"host port msg..."<<endl;22 return -1;23 }24 sockaddr_in s_in;25 memset(&s_in, 0, sizeof(s_in));26 s_in.sin_family = AF_INET;27 s_in.sin_addr.s_addr = inet_addr("127.0.0.1");//(args[1]);28 s_in.sin_port = htons(atoi(args[1]));29 30 cout<<"port"<<"\t"<<args[1]<<endl;31 int s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);32 if( s == -1)33 {34 cout<<"socket error"<<strerror(errno)<<endl;35 }36 37 socklen_t length = sizeof(sockaddr_in);38 if(-1 == connect(s, (sockaddr*)&s_in, length))39 {40 cout<<"connect error"<<strerror(errno)<<endl;41 close(s); 42 return -1;43 }44 for(;;)45 {46 char buffer[512];47 48 if(strcmp(args[2],"q")==0)49 break;50 ssize_t size = send(s, buffer, strlen(buffer),0);51 cout<<"socket num:"<<s<<endl;52 sprintf(buffer,"%s%s",args[2],"www.cnblogs.com/cyjwdm0503");53 size = send(s,args[2],strlen(args[2]),0);54 if( -1 == size)55 {56 cout<<"write error"<<strerror(errno)<<endl;57 close(s);58 return -1;59 }60 }61 close(s);62 63 }
Although here is Linux as an example, Windows and this is similar, reprinted please indicate the source address http://www.cnblogs.com/cyjwdm0503