Socket Programming: Multiplexing I/O server-side client.

Source: Internet
Author: User

In fact, in the previous TCP, we programmed to implement a multi-process, multi-threaded TCP server, but for this kind of TCP server, there is too much resource limitations. So we can use the multiplexed I/O model in the i/0 model to program.


His specific idea is that the current process can handle multiple corresponding times, record multiple descriptors, and then control the polling time state, when the response is generated we go to save the current response file descriptor, the connection processing/data transfer is OK. In a process to respond to multiple response times, we can greatly save the resources that our system consumes.


The function that operates on this is select ():

His function prototype is as follows:

650) this.width=650; "src=" Http://s1.51cto.com/wyfs02/M02/80/F1/wKioL1dFROezZP3zAAB9ATIP8PU712.png "title=" QQ picture 20160525141925.png "alt=" Wkiol1dfroezzp3zaab9atip8pu712.png "/>

First we don't look at the Select function itself, let's take a look at several FD functions under Select:

FD = FD, in fact very simple, is our file descriptor operation function.

About variables of type fd_set*: A set of file descriptors for some type of time behavior, called a descriptive phrase.

FD_CLR (INR fd,fd_set* set), used to clear the bits of the associated FD in the description phrase set

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

Fd_set (int fd,fd_set*set), used to set the bit of the associated FD in the description phrase set

Fd_zero (Fd_set *set), used to clear all bits that describe the set of a phrase.


Then let's take a look at the Select function:

The parameter Nfds is the maximum file descriptor value +1 that needs to be monitored;

The rdset,wrset,exset corresponds to a set of readable file descriptors that need to be detected, a set of writable file descriptors, and a different

A collection of common file descriptors.

The struct TIMEVAL structure is used to describe a length of time, if there is no event for the descriptor to be monitored during this time

Occurs when the function returns and the return value is 0.

The parameter timeout is a struct timeval, which is used to set the wait time for select (), whose structure is defined as follows:

650) this.width=650; "src=" Http://s3.51cto.com/wyfs02/M02/80/F2/wKiom1dFRVPBQZNdAAAmTwJH5NA018.png "title=" QQ picture 20160525142509.png "alt=" Wkiom1dfrvpbqzndaaamtwjh5na018.png "/>

If the parameter timeout is set to:

NULL: Indicates that select () No timeout,select will be blocked until a file descriptor has occurred

Event.

0: Detects only the state of the descriptor collection and then returns immediately without waiting for an external event to occur.

Specific time value: If no event occurs during the specified time period, select will time out to return.


function return value:

Successful execution returns the number of changes to the state of the file descriptor

Returns 0 if the representation has exceeded the timeout time before the state of the descriptive word has changed;

Returns 1 when an error occurs, and the reason for the error is stored in errno, at which time the parameters Readfds,writefds,exceptfds and

The value of timeout becomes unpredictable. The error value may be:

The EBADF file descriptor is invalid or the file is closed.

Eintr This call is interrupted by the signal.

EINVAL parameter n is a negative value.

Enomem core memory is low.


The key to understanding the Select model is to understand the fd_set, for illustrative convenience, take fd_set length of 1 bytes, each bit in Fd_set

can correspond to a file descriptor FD. The 1-byte-long fd_set can correspond to 8 fd maximum.

(1) Execute fd_set set; Fd_zero (&set); The set is represented by a bit 0000,0000.

(2) If fd=5, execute Fd_set (fd,&set), then SET to 0001,0000 (5th position 1)

(3) If you add fd=2,fd=1 again, set becomes 0001,0011

(4) Execute select (6,&set,0,0,0) blocking wait

(5) If a readable event occurs on the fd=1,fd=2, select returns, at which point the set becomes 0000,0011. Note: no events

The fd=5 that occurred was emptied.

Based on the above discussion, it is easy to derive the features of the Select model:

(1) The number of file descriptors that can be monitored depends on the value of sizeof (Fd_set). My side of the server sizeof (fd_set) =

512, each bit represents a file descriptor, then the maximum file descriptor supported on my server is 512*8=4096. Said

Adjustable, although adjustable, the upper limit is dependent on the value of the variable when compiling the kernel. I do not adjust the size of the Fd_set

Too interested, refer to the module in http://www.cppblog.com/CppExplore/archive/2008/03/21/45061.html

Type 2 (1) can effectively break the upper limit of file descriptors that can be monitored by SELECT.

(2) When the FD is added to the Select Monitor set, a data structure is used to save the array to the Select monitor set.

In the FD, one is used for re-select return, array as the source data and fd_set for Fd_isset judgment. The second is select

Once returned, the previously joined FD is emptied, and the FD is re-obtained from the array each time you start select

Join (Fd_zero first), scan array at the same time to obtain the FD maximum value maxfd, for the first parameter of select.

(3) Visible Select model must loop array (plus FD, fetch MAXFD) in front of SELECT, select returns Loop array

(Fd_isset determines if there is time to occur).


For server-side authoring using the Select function:

    1. All sock socket descriptors (file descriptors) generated by the TCP server can be summarized into a set of readable file descriptors.

    2. When we detect the sock socket of listen () to establish the connection accept (), if the confirmation is normal, that is, we accept () the resulting file descriptor, it is determined that this is a client/server connection link. Then we use the relevant function operation to carry out the information transmission,

    3. Timeout represents the time at which the query waits, and it is important to note that the timeout must be reset for each cycle.

    4. The description phrase is initialized at the beginning of each cycle, or the value of the description phrase is changed, resulting in an error if the timeout is exhausted and no response is generated.


Select Cons:

(1) Each call to select, the FD collection needs to be copied from the user state to the kernel state, the cost of FD is very large

(2) At the same time, each call to select requires a kernel traversal of all the FD passed in, which is also very expensive when FD is very large

(3) The number of file descriptors supported by Select is too small, the default is 1024.


Here is the code for I/O multiplexing:

Server-side:

#include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <stdlib.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #include <error.h> #include < Assert.h> #define &NBSP;_BACKLOG_&NBSP;5INT&NBSP;FDS[64];&NBSP;//File Descriptor collection//command line parameter error static void usage ( Const char *proc) {printf ("usage : %s [ip][port]\n", proc);} The server-side TCP link binds the listening state. Static int startup (Char *ip,int port) {assert (IP); Int sock = socket (AF_INET, sock_stream,0), if (sock < 0) {perror ("socket"); exit (1);} Int set = 1;        if (setsockopt (Sock, SOL_SOCKET ,  so_reuseaddr, &set, sizeof (set))  < 0)          {               perror ( "SetSockOpt");            exit (4);        }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"); Exit (2);} if (Listen (Sock,_backlog_)  < 0) {perror ("listen"); exit (3);} Return sock;} Int main (int argc,char *argv[]) {//To determine the command parameter line. if (argc != 3) {usage (argv[0]); exit (1);} Int port = atoi (argv[2]);char *ip = argv[1];int listen_sock =  Startup (Ip,port);int done = 0;int new_sock = -1;struct sockaddr_in  client;socklen_t len = sizeof (client); The first record parameter of the Int max_fd; //selet function///read-write event file descriptor Fd_set  reads;fd_set writes;int i = 0;int fds_num = sizeof (FDS)/sizeof (Fds[0] )//Initializes a set of file descriptors for (; I&NBSP;&LT;&NBsp;fds_num;++i) {fds[i] = -1;} The listen file descriptor currently exists. fds[0] = listen_sock;max_fd = fds[0];//the first call to the SELECT function to set the value of MAX_FD; while (!done) {//Initialize read-write file descriptor Fd_ ZERO (&reads); Fd_zero (&writes);//Set Listen_sock to reads, because when waiting for the request, it is equivalent to the current read operation. Fd_set (listen_sock,&reads);//Set up a round-finding schedule in multiplexing. struct timeval timeout = {5,0};//did not read the Add event to reads.; for (I = 1;i < fds _num; ++i) {if (fds[i] >0) {fd_set (fds[i],&reads); if (FDS[I]&NBSP;&GT;&NBSP;MAX_FD) {max_fd =  fds[i];}}} Switch (select (max_fd+1, &reads,&writes,null,null)) {case 0 ://timeout{printf ("Select  timeout "); break;} Case -1:{//errorperror ("select"); break;} default:{//returns the changed file description. i = 0;//iterates through all the file descriptor collections. for (; i<fds_num;++i) {//Confirm if the listening time is accept;if (fds[i] == listen_sock && fd_ ISSET (fds[i],&reads)) {new_sock = accept (Listen_sock, (struct sockaddr*) &client,&len) ; if (new_sock <0) {perror ("accept"); continue;} printf ("get a new connet...%d\n", New_sock); for (i = 0;i< fds_num;++i) {if (fds[i ] == -1) {fds[i] = new_sock;break;}} if (I == fds_num) {close (New_sock);}} Else if (Fds[i] > 0 &&fd_isset (fds[i],&reads))//normal event, but non-listening time, also represents the newly established NEW_ Sock {Char buf[1024];ssize_t s = read (fds[i],buf,sizeof (BUF)  -1), if (s > 0) { buf[s] =  ' + ';//printf ("client : %s\n", buf);p rintf ("client : %s", buf); Write (fds[ I],buf,sizeof (s) +1);} Else if (s == 0) {printf ("client quit...\n"); Close (Fds[i]); fds[i] = -1;} Else{}}else{}}}break;}} return 0;}

Client:

#include <stdio.h> #include <unistd.h> #include <string.h> #include <error.h> #include <sys/ types.h> #include <sys/socket.h> #include <arpa/inet.h> #define  _PORT_ 8111void  Process_conn_client (int s) {ssize_t size  = 0;char buffer[1024];while (1) {size  = read (0,buffer,1024); if (size > 0) {write (s,buffer,size); Size = read (S,buffer , 1024x768);buffer[size] =  ';p rintf ("server:%s", buffer);//write (1,buffer,size);}} Int main () {Int s;struct sockaddr_in server_sock;s = socket (AF_INET,SOCK_STREAM,0 ); if (s < 0) {printf ("sock error"); return 1;} Bzero (&server_sock,sizeof (Server_sock)); Server_sock.sin_family = af_inet;server_sock.sin_addr.s_ Addr = htonl (Inaddr_any); server_sock.sin_port = htons (_port_); Connect (s, (struct  sockaddr *) &server_sock,sizeof (server_sock));p rocess_conn_client (s); close (s); return 0;} 

Operation result;

650) this.width=650; "src=" Http://s4.51cto.com/wyfs02/M01/80/F3/wKiom1dFS4Gi5PATAACx9qqx5X4707.png "title=" QQ picture 20160525145105.png "alt=" Wkiom1dfs4gi5pataacx9qqx5x4707.png "/>

This article is from the "egg-left" blog, please be sure to keep this source http://memory73.blog.51cto.com/10530560/1783014

Socket Programming: Multiplexing I/O server-side client.

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.