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数组中原本就存在的'';最后输出换行符。

  • 相关阅读:
    Combobox的使用
    章节十、7-Xpath---Xpath中绝对路径相对路径的区别
    章节十、6-CSS---用CSS 定位子节点
    章节十、5-CSS---用CSS 通配符定位元素
    章节十、4-CSS Classes---用多个CSS Classes定位元素
    章节十、3-CSS Selector---用CSS Selector
    章节十、2-用Linktext和PartialLinkText、ClassName、TagName定位元素
    章节十、1-用ID和XPath、name定位元素
    章节九、5-IE Driver
    章节九、4-ChromDriver介绍
  • 原文地址:https://www.cnblogs.com/sunminming/p/12004103.html
Copyright © 2011-2022 走看看