Linux non-blocking IO (v) Implementation of non-blocking loopback server client using poll

Source: Internet
Author: User
Tags readable stdin

In the previous sections we discussed the basic concepts of nonblocking IO, the design of buffer and the implementation of non-blocking connect, which we now use to complete the client's writing.

As we have suggested in http://www.cnblogs.com/inevermore/p/4049165.html, the client needs to monitor stdin, stdout, and SOCKFD.

It's important to note that

Only the buffer can be written, only to listen to SOCKFD and stdin read events.

In the past in blocking IO, we always listen to SOCKFD read events, because whenever sockfd readable, we go to call the user's callback function to handle the read event, in the callback function requires the user to manually read buffer data. In other words, receiving data is the responsibility of the user, and the poll model only needs to remind the user to receive it.

In non-blocking IO, because poll uses a horizontal trigger, if the buffer is full and each read equals an invalid operation, the data is always stacked in the kernel, and poll is constantly triggered. this is in some way equal to polling. So we only listen for SOCKFD read events when the buffer is available.

Only when the buffer is readable can we listen to the write events of SOCKFD and stdout. Since there is no data to write, listening for write events has no practical meaning except for the constant triggering of poll.

It is necessary to reload the events array of poll before each execution of the poll.

The complete code is as follows:

#include"sysutil.h"#include"Buffer.h"intMainintargcChar Const*argv[]) {    //Create a client socket    intSOCKFD = Tcp_client (8934); //call the non-blocking connect function    intret = Nonblocking_connect (SOCKFD,"192.168.44.136",9981, the); if(ret = =-1) {fprintf (stderr,"Timeout. \ n");    Exit (Exit_failure); }    //set three fd to Non-blockingActivate_nonblock (SOCKFD);    Activate_nonblock (Stdin_fileno);    Activate_nonblock (Stdout_fileno); buffer_t Recvbuf; //SOCKFD, stdout, Bufferbuffer_t SendBuf;//stdin, SOCKFD, Buffer//Initializing buffersBuffer_init (&recvbuf); Buffer_init (&sendbuf); structPOLLFD pfd[Ten];  while(1)    {        //Initialize        intIX;  for(ix =0; IX! =3; ++ix) {PFD[IX].FD= -1; Pfd[ix].events=0; }        //Reload Events Array        if(Buffer_is_readable (&sendbuf)) {pfd[0].FD =SOCKFD; pfd[0].events |=kwriteevent; }        if(Buffer_is_writeable (&sendbuf)) {pfd[1].FD =Stdin_fileno; pfd[1].events |=kreadevent; }        if(Buffer_is_readable (&recvbuf)) {pfd[2].FD =Stdout_fileno; pfd[2].events |=kwriteevent; }        if(Buffer_is_writeable (&recvbuf)) {pfd[0].FD =SOCKFD; pfd[0].events |=kreadevent; }        //listen for FD array        intNready = Poll (PFD,3, the); if(Nready = =-1) Err_exit ("Poll"); Else if(Nready = =0) {printf ("timeout\n"); Continue; }        Else        {            inti;  for(i =0; I <3; ++i) {intFD =PFD[I].FD; if(FD = = sockfd && pfd[i].revents &kreadevent) {                    //receive data from SOCKFD to Recvbuf                    if(Buffer_read (&recvbuf, fd) = =0) {fprintf (stderr,"Server close.\n");                    Exit (exit_success); }                 }                                    if(FD = = sockfd && pfd[i].revents &kwriteevent) Buffer_write (&sendbuf, FD);//writes data from SendBuf to SOCKFD                if(FD = = Stdin_fileno && pfd[i].revents &kreadevent) {                    //receive data from stdin write SendBuf                    if(Buffer_read (&sendbuf, fd) = =0) {fprintf (stderr,"exit.\n");                    Exit (exit_success); }                 }                if(FD = = Stdout_fileno && pfd[i].revents &kwriteevent) Buffer_write (&recvbuf, FD);//output data from the RECVBUF to stdout            }        }    }}

As can be seen from the above code, most operations are encapsulated in the implementation of buffer.

To test the server, I use the Muduo library for the time being to write a code as follows:

#include <muduo/net/TcpServer.h>#include<muduo/net/InetAddress.h>#include<muduo/net/TcpConnection.h>#include<muduo/Base/timestamp.h>#include<muduo/net/EventLoop.h>#include<muduo/Base/logging.h>using namespaceMuduo;using namespacemuduo::net;voidOnMessage (ConstTcpconnectionptr &conn, Buffer *buf, Timestamp t) {    stringS (buf->retrieveallasstring ()); Log_info<<"recv msg:"<< s.size () <<"At :"<<t.toformattedstring (); Conn-send (s);}intMainintargcChar Const*argv[])    {EventLoop loop; InetAddress Addr ("192.168.44.136",9981); TCPServer Server (&loop, addr,"Echoserver"); Server.setmessagecallback (&onMessage);    Server.start ();    Loop.loop (); return 0;}

Readers who use the above code need to install the Muduo network library.

compile with the following command:

g++ server.cpp  -lmuduo_net-lmuduo_base-lpthread-o Server

The following uses poll to implement a non-blocking server side.

Linux non-blocking IO (v) Implementation of non-blocking loopback server client 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.