-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathlibeventHello.h
More file actions
184 lines (163 loc) · 5 KB
/
libeventHello.h
File metadata and controls
184 lines (163 loc) · 5 KB
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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
#pragma once
/*
* how to use init a tcp-server based on libevent
* how to use signal
* how to send message to the tcp-client
* 2018-11-30 , "conn_readcb", GUGW , how to receive message from the tcp-client \ reply the message to the tcp-client \ close when received the "stop"
*/
#include "stdafx.h"
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <signal.h>
#include <thread>
#ifndef _WIN32
#include <netinet/in.h>
# ifdef _XOPEN_SOURCE_EXTENDED
# include <arpa/inet.h>
# endif
#include <sys/socket.h>
#endif
#include <event2/bufferevent.h>
#include <event2/buffer.h>
#include <event2/listener.h>
#include <event2/util.h>
#include <event2/event.h>
#include "./chronoStudy.h"
static const char MESSAGE[] = "Hello, World!Hello, World!Hello, World!Hello, World!Hello, World!Hello, World!Hello, World!Hello, World!Hello, World!Hello, World!Hello, World!Hello, World!Hello, World!\r\n";
static const int PORT = 9995;
bool closeflag = false;
static void listener_cb(struct evconnlistener *, evutil_socket_t, struct sockaddr *, int socklen, void *);
static void conn_writecb(struct bufferevent *, void *);
static void conn_readcb(struct bufferevent *, void *);
static void conn_eventcb(struct bufferevent *, short, void *);
static void signal_cb(evutil_socket_t, short, void *);
static int testLibeventHello(int argc, char **argv)
{
struct event_base *base;
struct evconnlistener *listener;
struct event *signal_event;
struct sockaddr_in sin;
#ifdef _WIN32
WSADATA wsa_data;
WSAStartup(0x0201, &wsa_data);
#endif
//创建事件集,用于后续所有事件
base = event_base_new();
if (!base) {
fprintf(stderr, "Could not initialize libevent!\n");
return 1;
}
//初始化本地网络地址
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(PORT);
//利用libevent 建立监听绑定,当有新连接来时,触发listener_cb函数
listener = evconnlistener_new_bind(base, listener_cb, (void *)base,
LEV_OPT_REUSEABLE | LEV_OPT_CLOSE_ON_FREE, -1,
(struct sockaddr*)&sin,
sizeof(sin));
if (!listener) {
fprintf(stderr, "Could not create a listener!\n");
return 1;
}
//建立信号事件,回调函数
signal_event = evsignal_new(base, SIGINT, signal_cb, (void *)base);
//将信号事件加入到event_base中
if (!signal_event || event_add(signal_event, NULL)<0) {
fprintf(stderr, "Could not create/add a signal event!\n");
return 1;
}
//重要函数,循环监听注册的事件,若有,则调用相关的回调函数。
event_base_dispatch(base);
//释放监听,与evconnlistener_new_bind相对应
evconnlistener_free(listener);
//释放事件
event_free(signal_event);
//释放循环监听和分发
event_base_free(base);
printf("done\n");
return 0;
}
static void
listener_cb(struct evconnlistener *listener, evutil_socket_t fd,
struct sockaddr *sa, int socklen, void *user_data)
{
struct event_base *base = (struct event_base *)user_data;
struct bufferevent *bev;
bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);
if (!bev) {
fprintf(stderr, "Error constructing bufferevent!");
event_base_loopbreak(base);
return;
}
bufferevent_setcb(bev, conn_readcb, conn_writecb, conn_eventcb, NULL);
bufferevent_enable(bev, EV_WRITE);
bufferevent_enable(bev, EV_READ);
bufferevent_setwatermark(bev, EV_READ, 4, 4);
//bufferevent_disable(bev, EV_READ);
int len = 3;
int i = len;
while(i>0)
{
i--;
bufferevent_write(bev, MESSAGE, strlen(MESSAGE));
//printf("bufferevent_write\n");
//std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
printf("%s write %f KB\n", getSystemClock_microSeconds().c_str(), strlen(MESSAGE)*len/1024.0);
closeflag = false;
}
static void
conn_writecb(struct bufferevent *bev, void *user_data)
{
struct evbuffer *output = bufferevent_get_output(bev);
if (evbuffer_get_length(output) == 0) {
printf("%s flushed answer\n", getSystemClock_microSeconds().c_str());
std::this_thread::sleep_for(std::chrono::milliseconds(100));
if(closeflag)
bufferevent_free(bev);
}
else
{
printf("%s flushed answer1\n", getSystemClock_microSeconds().c_str());
}
}
static void
conn_readcb(struct bufferevent *bev, void *user_data)
{
char line[256];
int n;
evutil_socket_t fd = bufferevent_getfd(bev);
while (n = bufferevent_read(bev, line, 255), n > 0)
{
line[n] = '\0';
printf("fd=%u, read line: %s\n", fd, line);
}
char enter[] = "we received your message\n";
bufferevent_write(bev, enter, strlen(enter));
if(strcmp(line,"stop")==0)
closeflag = true;
}
static void
conn_eventcb(struct bufferevent *bev, short events, void *user_data)
{
if (events & BEV_EVENT_EOF) {
printf("Connection closed.\n");
}
else if (events & BEV_EVENT_ERROR) {
printf("Got an error on the connection: %s\n",
strerror(errno));/*XXX win32*/
}
/* None of the other events can happen here, since we haven't enabled
* timeouts */
bufferevent_free(bev);
}
static void
signal_cb(evutil_socket_t sig, short events, void *user_data)
{
struct event_base *base = (struct event_base *)user_data;
struct timeval delay = { 2, 0 };
printf("Caught an interrupt signal; exiting cleanly in two seconds.\n");
event_base_loopexit(base, &delay);
}