libevent Note 5: water level watermarks

bufferevent provides read and write triggers the callback and set the maximum buffer length, i.e., high water level is low:

  • Low water level: read callback function is the minimum length of the trigger data, when the data length of the input / output buffer is less than a low level, the read / write callback will not be triggered;
  • High water: receiving the maximum length of the buffer, when the data length of the input / output buffer is greater than a high level, it does not increase the data to the cache area.

Water level set function bufferevent_setwatermark

void bufferevent_setwatermark (struct bufferevent * bufev, short events, size_t lowmark, size_t highmark)
This function can be provided low-high water level designated event for a given bufferevent. If the events was set callback function to read water level is EV_READ; events set the water level to write the callback function is EV_WRITE was,

Demo

Server: After creating bufferevent and client connections, set the low water level to 6, the high water mark of 10.

//server.c
#include <arpa/inet.h>
#include <stdio.h>
#include <unistd.h>
#include <malloc.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <errno.h>
#include <event2/buffer.h>
#include <event2/event.h>
#include <event2/listener.h>
#include <event2/bufferevent.h>

// 读缓冲区回调
void read_cb(struct bufferevent *bev, void *arg)
{
    char buf[1024] = {0};   
    bufferevent_read(bev, buf, sizeof(buf));
    //这里不能直接输出字符串
    for(int i = 0; i < 20; ++i)
    {
       printf("%c", buf[i]);
    }
    printf("\n");
}
 
void cb_listener(struct evconnlistener *listener, evutil_socket_t fd, 
        struct sockaddr *addr, int len, void *ptr){
   
   struct sockaddr_in *addr_in = (struct socketaddr*)addr;
   printf("connect new client from: %s\n", inet_ntoa(addr_in->sin_addr));
   struct event_base* base = (struct event_base*)ptr;
   // 通信操作
   // 添加新事件
   struct bufferevent *bev;
   bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);
 
   // 给bufferevent缓冲区设置回调
   bufferevent_setcb(bev, read_cb, NULL, NULL, NULL);
   bufferevent_enable(bev, EV_READ);
   bufferevent_enable(bev, EV_WRITE);

   //设置读写的高低水位
   bufferevent_setwatermark(bev, EV_READ|EV_WRITE, 6, 10);  
}

int main(int argc, const char* argv[])
{
    // init server 
    struct sockaddr_in serv;
    memset(&serv, 0, sizeof(serv));
    serv.sin_family = AF_INET;
    serv.sin_port = htons(9995);
    serv.sin_addr.s_addr = htonl(INADDR_ANY);
 
    struct event_base* base;
    base = event_base_new();
    // 创建套接字
    // 绑定
    // 接收连接请求
    struct evconnlistener* listener;
    listener = evconnlistener_new_bind(base, cb_listener, base, 
                                  LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE, 
                                  36, (struct sockaddr*)&serv, sizeof(serv));
 
    event_base_dispatch(base);
    evconnlistener_free(listener);
    event_base_free(base);
    return 0;
}

Client:

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <event2/event.h>
#include <event2/bufferevent.h>
 
void send_cb(evutil_socket_t fd, short what, void *arg)
{
    char buf[1024] = {0}; 
    struct bufferevent* bev = (struct bufferevent*)arg;
    read(fd, buf, sizeof(buf));
    bufferevent_write(bev, buf, strlen(buf)+1);
}

int main(int argc, const char* argv[])
{
    struct event_base* base;
    base = event_base_new();
 
    struct bufferevent* bev;
    bev = bufferevent_socket_new(base, -1, BEV_OPT_CLOSE_ON_FREE);
 
    // 连接服务器
    struct sockaddr_in serv;
    memset(&serv, 0, sizeof(serv));
    serv.sin_family = AF_INET;
    serv.sin_port = htons(9995);
    evutil_inet_pton(AF_INET, "127.0.0.1", &serv.sin_addr.s_addr);
    bufferevent_socket_connect(bev, (struct sockaddr*)&serv, sizeof(serv));
 
    // 设置回调
    bufferevent_setcb(bev, read_cb, NULL, event_cb, NULL);
    bufferevent_enable(bev, EV_READ | EV_PERSIST);
    // 创建一个事件
    struct event* ev = event_new(base, STDIN_FILENO, 
                                 EV_READ|EV_PERSIST, send_cb, bev);

    event_add(ev, NULL); 
    event_base_dispatch(base);
    event_base_free(base);
    return 0;
}

The client sends data:

sunminming@sunminming:~/libevent/watermask$ ./client 
服务器已连接
a
qwertyuio

Data received by the server:

sunminming@sunminming:~/libevent/watermask$ ./server 
connect new client from: 127.0.0.1
a
qwertyu

Our total transmitted twice from the client information, send the first three characters: 'a', '\ n ', '\ 0'; 11 second transmission characters' q ',' w ', ' e ',' r ',' t ',' y ',' u ',' i ',' o ',' \ n ',' \ 0 ').
Thus, the read callback function output from the first 10 characters must be: 'a', '\ n ', '\ 0', 'q', 'w', 'e', 'r', 't', 'y ',' u '; after 10 also outputs a buf already present in the array' \ 0 '; newline final output.

Guess you like

Origin www.cnblogs.com/sunminming/p/12004103.html