In this article we will implement the buffer of the loopback server.
The implementation of buffer
The previous section mentions that non-blocking IO must have buffer. Once again, describe the design of the buffer:
One thing to add here is that Writeindex points to the first position of the free space.
There are three important invariant expressions :
1.0 <= readindex <= writeindex <= buffer_size
2. Writeindex–readindex is the number of bytes that can be read from buffer
3. Buffer_size–writeindex the number of bytes that can continue to be read as BUFFER
Also, after the data has been read, reset the subscript to 0.
According to my design, I used the structure to encapsulate a buffer, as follows:
#ifndef Buffer_h_#defineBuffer_h_#include<poll.h>#defineBuffer_size 1024typedefstruct { CharBuf_[buffer_size]; intReadindex_;//reading Data intWriteindex_;//Write Data} buffer_t;voidBuffer_init (buffer_t *BT);intBuffer_is_readable (buffer_t *BT);intBuffer_is_writeable (buffer_t *BT);intBuffer_read (buffer_t *BT,intsockfd);intBuffer_write (buffer_t *BT,intsockfd);#defineKreadevent (Pollin | POLLPRI)#defineKwriteevent (Pollout | Pollwrband)#endif //Buffer_h_
The buffer here first takes a fixed length and can be changed to a dynamic array later.
Let's implement each of the functions of buffer.
The first is initialization, the memory is zeroed, and the subscript is set to 0.
void buffer_init (buffer_t *bt) { memset (BT0sizeof(bt->buf_)); BT0; BT0;}
Whether the buffer can read the data, need to determine whether (Writeindex–readindex) is greater than 0
int buffer_is_readable (buffer_t *bt) { return bt->writeindex_ > bt-> readindex_;}
If the buffer is writable, you need to determine if there is free space.
int buffer_is_writeable (buffer_t *bt) { return buffer_size > bt->writeindex _;}
The next step is to call the Read function, buffer reads the data from FD, and the last parameter of read is the remaining space in buffer.
intBuffer_read (buffer_t *BT,intsockfd) { intNread = Read (SOCKFD, &bt->buf_[bt->writeindex_], buffer_size-bt->writeindex_); if(Nread = =-1) { if(errno! =Ewouldblock) Err_exit ("Read FD error"); return-1; } Else{BT->writeindex_ + =nread; returnnread; }}
Finally, the output operation, the last parameter that writes the data in buffer to Sockfd,write is the number of bytes existing in buffer.
intBuffer_write (buffer_t *BT,intsockfd) { intNwriten = Write (SOCKFD, &bt->buf_[bt->readindex_], bt->writeindex_-bt->readindex_); if(Nwriten = =-1) { if(errno! =Ewouldblock) Err_exit ("Write FD Error"); return-1; } Else{BT->readindex_ + =Nwriten; if(Bt->readindex_ = = bt->writeindex_) {BT->readindex_ = Bt->writeindex_ =0; } returnNwriten; }}
The implementation of buffer is complete.
The client that writes back to the server is started later.
Linux non-blocking IO (iii) Implementation of buffer buffers in nonblocking IO