Linux non-blocking IO (vi) Implementation of non-blocking server-side using poll

Source: Internet
Author: User

For the poll model listener events and return events, we define the following macros:

#define kreadevent (Pollin | POLLPRI)#define kwriteevent (pollout | Pollwrband)#define kreadrevent (Pollin | Pollpri | Pollrdhup)#define kwriterevent (pollout)

We explained earlier why the non-blocking IO must have buffers. In fact, for server, each TCP connection should have two buffers, one for input and one for output.

sockfd–> inputbuffer–> User space –> processing data –> Get results –> outputbuffer–> SOCKFD

But this example is simply a back-up service that receives data immediately, so we only use one buffer.

For each TCP connection, we correspond to a data structure such as:

struct {    // represents a TCP connection

Then we need to establish a correspondence between FD and the corresponding tcp_connection_t. I use the following array:

// provides mappings from FD to TCP connections

This array is initialized to NULL, then I use FD as subscript, that is, when I need to process an FD, I can find the corresponding tcp_connection_t pointer with the FD as subscript. This is essentially the idea of a hash table .

The logic for using tcp_connection_t is:

Whenever you accept a new connection, a new tcp_connection_t is created dynamically, and its pointer is saved to a location in which PEERFD is subscript .

Each time the connection is closed, the memory needs to be freed and the pointer is reset to NULL.

I wrote all the code in the main function, because buffer was previously encapsulated, the readability of the code was improved, and our business logic was simple, further encapsulated, but less readable.

There are several similarities with the client:

Listen for read events only if the buffer has free space

Listen for write events only when the buffer has data

So we need to reload the FD's listener event before each poll call.

The overall framework for server code is as follows:

// Initialize Poll  while (1) {    // reload fd array     //poll system call     //  handle Read and write events for each FD sequentially }

So the complete code is as follows:

#define_gnu_source/* See Feature_test_macros (7) */#include<sys/socket.h>#include"sysutil.h"#include"Buffer.h"#include<assert.h>#defineEvents_size 1024typedefstruct{buffer_t buffer_;} tcp_connection_t;//represents a TCP connectiontcp_connection_t*connsets[events_size];//provides mappings from FD to TCP connectionsintMainintargcChar Const*argv[]) {    //Get listener FD    intLISTENFD = Tcp_server ("localhost",9981); //set the Listen FD to non-blockingActivate_nonblock (LISTENFD); //Initialize Connsets    inti;  for(i =0; i < events_size; ++i) {connsets[i]=NULL; }    //Initialize Poll    structPOLLFD Events[events_size];  for(i =0; i < events_size; ++i) events[i].fd= -1; events[0].FD =LISTENFD; events[0].events =kreadevent; intMaxi =0;  while(1)    {        //Reload Events Array        inti;  for(i =1; i < events_size; ++i) {intFD =EVENTS[I].FD; Events[i].events=0;//Reset Events            if(FD = =-1)                Continue; ASSERT (CONNSETS[FD]!=NULL); //Listen for write events when data is readable in buffer            if(Buffer_is_readable (&connsets[fd]->buffer_)) {events[i].events|=kwriteevent; }            //The Read event is only monitored when there is free space in buffer            if(Buffer_is_writeable (&connsets[fd]->buffer_)) {events[i].events|=kreadevent; }        }        //Poll Call        intNready = Poll (events, Maxi +1, the); if(Nready = =-1) Err_exit ("Poll"); Else if(Nready = =0) {printf ("Poll timeout.\n"); Continue; }                //Handling LISTENFD        if(events[0].revents &kreadevent) {            //accept a new customer FD            intPEERFD = ACCEPT4 (LISTENFD, NULL, NULL, Sock_nonblock |sock_cloexec); if(PEERFD = =-1) Err_exit ("Accept4"); //New TCP connectiontcp_connection_t *pt = (tcp_connection_t*) malloc (sizeof(tcp_connection_t)); Buffer_init (&pt->buffer_); //Place the TCP connection into the ConnsetsCONNSETS[PEERFD] =pt; //put into events array            inti;  for(i =0; i < events_size; ++i) {if(EVENTS[I].FD = =-1) {EVENTS[I].FD= PEERFD;//There's no need to listen to FD                    if(I >Maxi) Maxi= i;//Update Maxi                     Break; }            }            if(i = =events_size) {fprintf (stderr,"Too many clients\n");            Exit (Exit_failure); }        }        //Process Customer FD//int i;         for(i =1; I <= Maxi; ++i) {intSOCKFD =EVENTS[I].FD; if(SOCKFD = =-1)                Continue; //Remove the pointertcp_connection_t *pt =CONNSETS[SOCKFD]; Assert (PT!=NULL); if(Events[i].revents & Kreadrevent)//reading Data            {                if(Buffer_read (&pt->buffer_, sockfd) = =0)                {                    //CloseEVENTS[I].FD =-1;                    Close (SOCKFD);                    Free (PT); CONNSETS[SOCKFD]=NULL; Continue;//continue the next cycle                }             }            if(Events[i].revents & Kwriterevent)//can send data{buffer_write (&pt->Buffer_, SOCKFD);    }}} close (LISTENFD); return 0;}

It is important to note that, regarding accept, I am using ACCPET4, which is a new system call from Linux:

int accept4 (intstructint flags);

The difference from accept is that ACCEPT4 can specify a non-blocking flag bit.

Use Epoll below.

Linux non-blocking IO (vi) Implementation of non-blocking server-side using poll

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.