Posts p12 Linux高性能服务器编程-- libevent 库
Post
Cancel

p12 Linux高性能服务器编程-- libevent 库

1. demo1 libevent 的使用 常规事件

write 客户端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
//
// Created by xm on 2022/4/24.
//

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <fcntl.h>
#include <event2/event.h>

void write_cb(evutil_socket_t fd, short what ,void *arg){
    // 写管道
    char buf[1024];
    static int num = 0;
    sprintf(buf,"hello word %d \n",num++);
    write(fd,buf, strlen(buf) + 1);

    sleep(1);
}

// 读管道
int main(int argc,const char* argv[]){

    // open file
    int fd = open("myfifo",O_WRONLY|O_NONBLOCK);
    if (fd == -1){
        perror("open error1111111");
        exit(1);
    }

    // 创建base
    struct event_base *base = NULL;
    base = event_base_new();

    // 创建事件
    struct event* ev = NULL;
    ev = event_new(base,fd,EV_WRITE | EV_PERSIST, write_cb,NULL);  // EV_PERSIST 可持续读 与 just 读一次

    // 添加事件
    event_add(ev,NULL);

    // 事件循环
    event_base_dispatch(base);

    // 释放资源
    event_free(ev);
    event_base_free(base);
    close(fd);

    return 0;
}

read 服务器端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
//
// Created by xm on 2022/4/24.
//

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <fcntl.h>
#include <event2/event.h>

void read_cb(evutil_socket_t fd, short what ,void *arg){
    // 读管道
    char buf[1024];
    int len = read(fd,buf,sizeof(buf));
    printf("read event: &s");
    printf("data len = %d, buf = %s\n",len,buf);
    sleep(1);
}

// 读管道
int main(int argc,const char* argv[]){
    unlink("myfifo");
    mkfifo("myfifo",0644);

    // open file
    int fd = open("myfifo",O_RDONLY|O_NONBLOCK);
    if (fd == -1){
        perror("open error");
    }

    // 创建base
    struct event_base *base = NULL;
    base = event_base_new();

    // 创建事件
    struct event* ev = NULL;
    ev = event_new(base,fd,EV_READ | EV_PERSIST, read_cb,NULL);

    // 添加事件
    event_add(ev,NULL);

    // 事件循环
    event_base_dispatch(base);

    // 释放资源
    event_free(ev);
    event_base_free(base);
    close(fd);

    return 0;
}

2. buffer 事件

服务器端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
//
// Created by xm on 2022/4/24.
//

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <fcntl.h>
#include <event2/event.h>
#include <arpa/inet.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));
    printf("client say : %s\n",buf);

    char *p = "我是服务器 我已经成功的接收到你发送的数据";
    bufferevent_write(bev,p,strlen(p)+1);

    sleep(1);
}

// 写回调
void write_cb(struct bufferevent *bev,void *arg){
    printf(" 我是服务器  我已经成功把数据写回客户端");
}

// 事件回调
void event_cb(struct bufferevent *bev,short events,void *arg){
    if (events & BEV_EVENT_EOF){
        printf("connection closed\n");
    } else if (events & BEV_EVENT_ERROR){
        printf("some other error\n");
    }

    bufferevent_free(bev);
    printf("资源已经被释放");
}

// 监听器回调函数
void cb_listerer(struct evconnlistener *listener,evutil_socket_t fd,struct sockaddr *addr,int len,void *ptr){
    printf("connect new client\n");
    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,write_cb,event_cb,NULL);

    // 启用bufferevent 的 读缓冲
    bufferevent_enable(bev,EV_READ);
}

int main(){
    struct sockaddr_in serv;
    memset(&serv,0,sizeof(serv));
    serv.sin_port = htonl(9876);
    serv.sin_family = AF_INET;
    serv.sin_addr.s_addr = htonl(INADDR_ANY);

    struct event_base *base;
    base = event_base_new();

    struct evconnlistener *listerer; // 监听器
    /*
     * 为什么要传递两个base参数?   cb_listerer(void *ptr) 用来接收第二个base
     */
    listerer = evconnlistener_new_bind(base,cb_listerer,base,LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE,36,
                                       (struct sockaddr*)&serv,sizeof(serv));  // LEV_OPT_REUSEABLE 端口复用   36  链接上限


    // 启动循环监听
    event_base_dispatch(base);
    evconnlistener_free(listerer);
    event_base_free(base);
    return 0;
}

客户端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
//
// Created by xm on 2022/4/24.
//

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <fcntl.h>
#include <event2/event.h>
#include <arpa/inet.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));
    printf("client say : %s\n",buf);

    char *p = "我是客户端我已经成功的接收到你发送的数据";
    bufferevent_write(bev,p,strlen(p)+1);

    sleep(1);
}

// 写回调
void write_cb(struct bufferevent *bev,void *arg){
    printf(" 我是客户端  我已经成功把数据发送给服务器");
}

// 事件回调
void event_cb(struct bufferevent *bev,short events,void *arg){
    if (events & BEV_EVENT_EOF){
        printf("connection closed\n");
    } else if (events & BEV_EVENT_ERROR){
        printf("some other error\n");
    }

    bufferevent_free(bev);
    printf("资源已经被释放");
}

// 监听器回调函数
void cb_listerer(struct evconnlistener *listener,evutil_socket_t fd,struct sockaddr *addr,int len,void *ptr){
    printf("connect new client\n");
    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,write_cb,event_cb,NULL);

    // 启用bufferevent 的 读缓冲
    bufferevent_enable(bev,EV_READ);
}

void read_terminal(evutil_socket_t fd,short what,void *arg){
    char buf[1024];
    int len = read(fd,buf,sizeof(buf));

    struct  bufferevent *bev = (struct bufferevent*) arg;
    bufferevent_write(bev,buf,len+1);
}

int main(){


    struct event_base *base;
    base = event_base_new();

    int fd = socket(AF_INET,SOCK_STREAM,0);

    // 通信的fd放到bufferevent中
    struct bufferevent *bev = NULL;
    bev = bufferevent_socket_new(base,fd,BEV_OPT_CLOSE_ON_FREE);

    struct sockaddr_in serv;
    memset(&serv,0,sizeof(serv));
    serv.sin_port = htonl(9876);
    serv.sin_family = AF_INET;
    inet_pton(AF_INET,"127.0.0.1",&serv.sin_addr);

    // 链接到服务器
    bufferevent_socket_connect(bev,(struct sockaddr*)&serv,sizeof(serv));

    // 设置回调
    bufferevent_setcb(bev,read_cb,write_cb,event_cb,NULL);

    // 创建事件
    struct event *ev = event_new(base,STDIN_FILENO,EV_READ | EV_PERSIST,read_terminal,bev);


    // 添加事件
    event_add(ev,NULL);
    event_base_dispatch(base);
    event_free(ev);
    event_base_free(base);


    return 0;
}
This post is licensed under CC BY 4.0 by the author.

Contents

Trending Tags