zoukankan      html  css  js  c++  java
  • libevent笔记5:水位watermarks

    bufferevent中提供了对读写回调的触发条件及最大缓存长度的设置,即低高水位:

    • 低水位:是读写回调函数的最低触发数据长度,当输入/输出缓存区中的数据长度小于低水位时,读/写回调函数不会被触发;
    • 高水位:是缓存区的最大接收长度,当输入/输出缓存区中的数据长度大于高水位时,不会继续向缓存区中增加数据。

    水位设置函数bufferevent_setwatermark

    void bufferevent_setwatermark (struct bufferevent *bufev, short events, size_t lowmark, size_t highmark)
    该函数能够为一个给定的bufferevent设置指定事件的低高水位。若events为EV_READ则为设置读回调函数的水位;events为EV_WRITE则为设置写回调函数的水位,

    Demo

    服务端:在创建了与客户端连接的bufferevent后,设置低水位为6,高水位为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("
    ");
    }
     
    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
    ", 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;
    }
    
    

    客户端:

    #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;
    }
    

    客户端发送数据:

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

    服务器接收的数据:

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

    我们从客户端一共发送了两次信息,第一次发送3个字符:'a',' ','';第二次发送11个字符'q','w','e','r','t','y','u','i','o',' ','')。
    因此,读回调函数输出的前10个字符应该为:'a',' ','','q','w','e','r','t','y','u';之后还输出了10个buf数组中原本就存在的'';最后输出换行符。

  • 相关阅读:
    swift 第十四课 可视化view: @IBDesignable 、@IBInspectable
    swift 第十三课 GCD 的介绍和使用
    swift 第十二课 as 的使用方法
    swift 第十一课 结构体定义model类
    swift 第十课 cocopod 网络请求 Alamofire
    swift 第九课 用tableview 做一个下拉菜单Menu
    swift 第八课 CollectView的 添加 footerView 、headerView
    swift 第七课 xib 约束的优先级
    swift 第六课 scrollview xib 的使用
    swift 第五课 定义model类 和 导航栏隐藏返回标题
  • 原文地址:https://www.cnblogs.com/sunminming/p/12004103.html
Copyright © 2011-2022 走看看