From Epoll build muduo-8 to join the send buffer and receive buffer

Source: Internet
Author: User
Tags epoll naming convention

Mini-muduo Version Transfer Gate
Version 0.00 Building Muduo-1 Mini-muduo Introduction from Epoll
Version 0.01 builds the muduo-2 simplest epoll from Epoll
Version 0.02 adds the first class from the Epoll build muduo-3, by the way reactor
Version 0.03 from Epoll build muduo-4 join Channel
Version 0.04 builds muduo-5 from Epoll to join Acceptor and tcpconnection
Version 0.05 builds muduo-6 from Epoll to join EventLoop and Epoll
Version 0.06 from Epoll build muduo-7 join Imuduouser
Version 0.07 from Epoll build muduo-8 join send buffer and receive buffer
Version 0.08 build Muduo-9 from Epoll add onwritecomplate callback and buffer
Version 0.09 builds muduo-10 timer timer from Epoll
Version 0.11 building muduo-11 single-threaded reactor network model from Epoll
Version 0.12 building muduo-12 multithreaded code admission from Epoll
Version 0.13 build MUDUO-13 reactor + ThreadPool molding from Epoll

Mini-muduo v0.07 version, this version is added to the send buffer and receive the initial version of the buffer, follow-up v0.08 perfect the implementation of the buffer. Mini-muduo complete and operational examples can be downloaded from GitHub, using the command git checkout v0.07 can switch to this version, online Browsing this version here

1 Why there is a send buffer and receive buffer, the Muduo author has already explained in detail in <<7.4.2 why non-blocking application layer buffer is required in network programming. >> Suggested that the students have the conditions to read directly. I think this part of the knowledge is very important, so I will extract the contents of the book again. We treat the two buffers separately.

First, the tcpconnection must have an output buffer.

Suppose the program wants to send 100k data over a TCP connection, but in the write system call, the operating system only accepted 80k, and as a user you do not know when you have the opportunity to send the remaining 20k, you have to keep the 20k data, in fact, save this 20k data should be the network library task. The user of the library should only be responsible for calling Tcpconnection::send () to tell the network library that it wants to send 100k data, since then the user should not worry about the data, how many to send each time, still have how many, the next hair how much should be completed by the network library.

Second, the tcpconnection must have an input buffer.

TCP is a borderless byte-throttling protocol in which the receiving party must process "the data received does not yet constitute a full day message" and "data received two messages at a time". Assuming that the sender sent two 1k messages (a total of 2k), the data received by the receiver may be:

1 one-time 2k data received

2 minutes two times received, first 0.6k, second 1.4k

3 minutes two times received, first 1.4k, second 0.6k

4 minutes two times received, first 1k, second 1k

5 minutes three times received, first 0.6k, second 0.8k, third 0.6k

6 anything else possible. In general, the probability that a message block of length n bytes arrives has a "2 N-th-1" type

So the network library must receive the message one at a time, and give the user a chance to get a notification when a single message arrives.

2 Output Buffer implementation: Tcpconnection added a member variable _outbuf representing the send buffer. The user sends the 100k data through the Tcpconnection::send to the network library, the network library first checks whether the output buffer is empty (_outbuf->empty ()), and if NULL indicates that there is no data waiting to be sent, Direct the 100k data to the write system call, see how much the operating system can accept, and then add the rest of the data not sent to play to the end of the output buffer. If the send buffer is not empty, the description has accumulated some data before this operation will not attempt to write, directly append 100k data to the send buffer. Note The Epollout event is registered to the Epoll file descriptor (tcpconnection.cc Line 98) After the data is added to the send buffer. This is the only way to receive notification of the Epoll file descriptor to continue sending the remaining data. When the operating system found that its buffer has more free space, through the epoll_wait return to inform the network library, you can continue to send, when the channel::handlewrite is triggered, Channel:: Handlewrite calls to Tcpconnection::handlewrite, which continues to send the remaining data through write, and cancels the attention Epollout event (tcpconnection.cc 76 rows) After all data has been sent. Canceling attention to Epollout is critical, and if not, epoll_wait will return epollout every time epoll_wait () is invoked, because the network library is notified whenever more send buffers can be filled in the operating system. The network library, because there is no more data to send to the operating system caused its endless notifications.

3 implementation of the input buffer: Tcpconnection adds a member variable _inbuf that represents the receive buffer, and when each handleread () callback is invoked, reads the data using the read system call and appends it to the input buffer and notifies the user. Adjust the buffer length of the work to the user to deal with, meet the following entry 6 echoserver changes.

4 Modify the Epolle::update () method, because the original only need to focus on the Epollin event, so epoll_ctl the second parameter only need to pass in the Clt_add, now because the implementation of the send buffer, so pay attention to and cancel the concern Epollout, so Epoll _ctl The second argument is passed to the clt_mod at some point. We use the same processing method as the original Muduo, add an int _index member variable for channel, the new channel This value is knew (value is-1), at this time the call Epoll::update use Ctl_add, after the call will be _ Index is set to _kadded (value is 1), subsequent call update is turned into Ctl_mod, which is used to add and delete epollout events.

5 modifies the Ichannelcallback interface and adds a Handlewrite callback for sending the buffer, which is triggered when Epoll_wait returns Epollout event. Several naming convention issues have been modified. Modify the parameter list of the Handleread::handlewrite () method, remove the int socket parameter, and take it from the channel, because this FD has been saved in the channel, there is no need to pass it here.

6 Imuduouser and Echoserver are changed, and the second parameter in the Imuduouser OnMessage interface is changed from const string& to string*. In the previous version, the data is one-way delivery, the network library to inform users of new data arrived, regardless of whether the customer read the data, the network library will be notified after onmessage the user to discard the data (see v0.06 version tcpconnection.cc 56 lines, Local variables used are automatically destroyed, and users must cache this part of the data themselves if they need a message to be complete through multiple onmessage callbacks. Since this version is replaced by the network library to implement the receive buffer, the user must tell the network library how much data he has read and the databases can be discarded. The buffer class specifically used as buffers in this release has not yet been implemented, so I simply pass a string* that the user discards the data received directly from the buffer. At the same time, Echoserver uses the following code when reading

    while (Data->size () > Message_length)
    {
        ...
    }
The reason for using while instead of if is that if you receive a full n message at once, the if can only handle the first one and ignore the following. Echoserver added code is also called codec (codec), if in order to make the program easier to understand, you can put this piece of implementation into a separate class, the role is whenever a complete message is received, notify the user program.

7 on the implementation of the input and output buffers, there are several obvious problems, first of all, Onwritecomplate callback has not been implemented, users do not know when they send the data all to the operating system. Secondly, the buffer class was not implemented, but it was simply replaced with std::string. These two issues will be resolved in the next release, the v0.08 version.

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.