libevent_server 服务器程序详细注释
来源:互联网 发布:双色球选红球算法 编辑:程序博客网 时间:2024/06/05 11:20
// 引入常用Linux系统头文件
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <signal.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
// 引入libevent 2.x相关的头文件
#include <event2/bufferevent.h>
#include <event2/buffer.h>
#include <event2/listener.h>
#include <event2/util.h>
#include <event2/event.h>
//cJOSN引入的头文件
#include "cJSON.h"
// 定义字符串常量,将会回应给Client用
static const char MESSAGE[] = "Hello, World!\n";
// server监听的端口
static const int PORT = 9995;
// 定义几个event callback的prototype(原型)
void listener_cb(struct evconnlistener * ,
evutil_socket_t,
struct sockaddr * ,
int socklen,
void * );
void conn_writecb(struct bufferevent * , void * );
void conn_eventcb(struct bufferevent * , short, void * );
void signal_cb(evutil_socket_t, short, void * );
void readcb(struct bufferevent* bev, void * ptr)
{
char buf[1024];
int n;
//从evbuffer获取数据到bufferevent中
struct evbuffer* input = bufferevent_get_input(bev);
//抽取evbuffer中的数据并输出到标准输出
while ((n = evbuffer_remove(input, buf, sizeof(buf)))>0)
{
fwrite(buf, 1, n, stdout);
}
cJSON *js = NULL;
js = cJSON_Parse(buf);
if(NULL == js)
{
perror("js");
return;
}
cJSON *header = cJSON_GetObjectItem(js,"header");
cJSON *number = cJSON_GetObjectItem(js,"number");
cJSON *ip = cJSON_GetObjectItem(js,"ip");
printf("header=%s\n", header->valuestring);
printf("number=%d\n", number->valueint);
printf("ip=%s\n", ip->valuestring);
}
// 监听端口的event callback
void listener_cb(struct evconnlistener * listener, evutil_socket_t fd,struct sockaddr * sa, int socklen, void * user_data)
{
printf("listener\n");
struct event_base * base = user_data;
struct bufferevent * bev;
// 新建一个bufferevent,设定BEV_OPT_CLOSE_ON_FREE,
// 保证bufferevent被free的时候fd也会被关闭
bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);
if (!bev)
{
fprintf(stderr, "Error constructing bufferevent!");
event_base_loopbreak(base);
return;
}
// 设定写buffer的event和其它event
bufferevent_setcb(bev, readcb, conn_writecb, conn_eventcb, NULL);
// 开启向fd中写的event
bufferevent_enable(bev, EV_WRITE);
// 关闭从fd中读写入buffer的event
//bufferevent_disable(bev, EV_READ);
//开启向fd中读的event
bufferevent_enable(bev, EV_READ);
// 向buffer中写入"Hello, World!\n"
// 上面的操作保证在fd可写时,将buffer中的内容写出去
bufferevent_write(bev, MESSAGE, strlen(MESSAGE));
}
// 每次fd可写,数据非阻塞写入后,会雕也难怪conn_writecb
// 这个函数每次检查eventbuffer的剩余大小,如果为0
// 表示数据已经全部写完,将eventbuffer free掉
// 由于在上面设定了BEV_OPT_CLOSE_ON_FREE,所以fd也会被关闭
void conn_writecb(struct bufferevent * bev, void * user_data)
{
struct evbuffer * output = bufferevent_get_output(bev);
if (evbuffer_get_length(output) == 0)
{
printf("flushed answer\n");
//bufferevent_free(bev);
}
}
// 处理读、写event之外的event的callback
void conn_eventcb(struct bufferevent * bev, short events, void * user_data)
{
if (events & BEV_EVENT_EOF) {
// Client端关闭连接
printf("Connection closed.\n");
} else if (events & BEV_EVENT_ERROR) {
// 连接出错
printf("Got an error on the connection: %s\n",
strerror(errno));
}
// 如果还有其它的event没有处理,那就关闭这个bufferevent
bufferevent_free(bev);
}
// 信号处理event,收到SIGINT (ctrl-c)信号后,延迟2s退出event循环
void signal_cb(evutil_socket_t sig, short events, void * user_data)
{
struct event_base * base = user_data;
struct timeval delay = { 2, 0 };
printf("Caught an interrupt signal; exiting cleanly in two seconds.\n");
event_base_loopexit(base, &delay);
}
// 定义标准的main函数
int main(int argc, char ** argv)
{
// event_base是整个event循环必要的结构体
struct event_base * base = event_base_new();
// 初始化sockaddr_in结构体,监听在0.0.0.0:9995
struct sockaddr_in sin;
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(PORT);
// bind在上面制定的IP和端口,同时初始化listen的事件循环和callback:listener_cb
// 并把listener的事件循环注册在event_base:base上
struct evconnlistener * listener = NULL;
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)
{
// 如果发生任何错误,向stderr(标准错误输出)打一条日志,退出
fprintf(stderr, "Could not create a listener!\n");
return 1;
}
#if 0
// 创建并初始化信号处理event
struct event *signal_event = evsignal_new(base, SIGINT, signal_cb, (void * )base);
//把这个callback放入base中
if (!signal_event || event_add(signal_event, NULL)<0)
{
fprintf(stderr, "Could not create/add a signal event!\n");
return 1;
}
#endif
// 程序将在下面这一行内启动event循环,只有在调用event_base_loopexit后
// 才会从下面这个函数返回,并向下执行各种清理函数,导致整个程序退出
event_base_dispatch(base);
// 各种清理free
evconnlistener_free(listener);
// event_free(signal_event);
event_base_free(base);
printf("done\n");
return 0;
}
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <signal.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
// 引入libevent 2.x相关的头文件
#include <event2/bufferevent.h>
#include <event2/buffer.h>
#include <event2/listener.h>
#include <event2/util.h>
#include <event2/event.h>
//cJOSN引入的头文件
#include "cJSON.h"
// 定义字符串常量,将会回应给Client用
static const char MESSAGE[] = "Hello, World!\n";
// server监听的端口
static const int PORT = 9995;
// 定义几个event callback的prototype(原型)
void listener_cb(struct evconnlistener * ,
evutil_socket_t,
struct sockaddr * ,
int socklen,
void * );
void conn_writecb(struct bufferevent * , void * );
void conn_eventcb(struct bufferevent * , short, void * );
void signal_cb(evutil_socket_t, short, void * );
void readcb(struct bufferevent* bev, void * ptr)
{
char buf[1024];
int n;
//从evbuffer获取数据到bufferevent中
struct evbuffer* input = bufferevent_get_input(bev);
//抽取evbuffer中的数据并输出到标准输出
while ((n = evbuffer_remove(input, buf, sizeof(buf)))>0)
{
fwrite(buf, 1, n, stdout);
}
cJSON *js = NULL;
js = cJSON_Parse(buf);
if(NULL == js)
{
perror("js");
return;
}
cJSON *header = cJSON_GetObjectItem(js,"header");
cJSON *number = cJSON_GetObjectItem(js,"number");
cJSON *ip = cJSON_GetObjectItem(js,"ip");
printf("header=%s\n", header->valuestring);
printf("number=%d\n", number->valueint);
printf("ip=%s\n", ip->valuestring);
}
// 监听端口的event callback
void listener_cb(struct evconnlistener * listener, evutil_socket_t fd,struct sockaddr * sa, int socklen, void * user_data)
{
printf("listener\n");
struct event_base * base = user_data;
struct bufferevent * bev;
// 新建一个bufferevent,设定BEV_OPT_CLOSE_ON_FREE,
// 保证bufferevent被free的时候fd也会被关闭
bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);
if (!bev)
{
fprintf(stderr, "Error constructing bufferevent!");
event_base_loopbreak(base);
return;
}
// 设定写buffer的event和其它event
bufferevent_setcb(bev, readcb, conn_writecb, conn_eventcb, NULL);
// 开启向fd中写的event
bufferevent_enable(bev, EV_WRITE);
// 关闭从fd中读写入buffer的event
//bufferevent_disable(bev, EV_READ);
//开启向fd中读的event
bufferevent_enable(bev, EV_READ);
// 向buffer中写入"Hello, World!\n"
// 上面的操作保证在fd可写时,将buffer中的内容写出去
bufferevent_write(bev, MESSAGE, strlen(MESSAGE));
}
// 每次fd可写,数据非阻塞写入后,会雕也难怪conn_writecb
// 这个函数每次检查eventbuffer的剩余大小,如果为0
// 表示数据已经全部写完,将eventbuffer free掉
// 由于在上面设定了BEV_OPT_CLOSE_ON_FREE,所以fd也会被关闭
void conn_writecb(struct bufferevent * bev, void * user_data)
{
struct evbuffer * output = bufferevent_get_output(bev);
if (evbuffer_get_length(output) == 0)
{
printf("flushed answer\n");
//bufferevent_free(bev);
}
}
// 处理读、写event之外的event的callback
void conn_eventcb(struct bufferevent * bev, short events, void * user_data)
{
if (events & BEV_EVENT_EOF) {
// Client端关闭连接
printf("Connection closed.\n");
} else if (events & BEV_EVENT_ERROR) {
// 连接出错
printf("Got an error on the connection: %s\n",
strerror(errno));
}
// 如果还有其它的event没有处理,那就关闭这个bufferevent
bufferevent_free(bev);
}
// 信号处理event,收到SIGINT (ctrl-c)信号后,延迟2s退出event循环
void signal_cb(evutil_socket_t sig, short events, void * user_data)
{
struct event_base * base = user_data;
struct timeval delay = { 2, 0 };
printf("Caught an interrupt signal; exiting cleanly in two seconds.\n");
event_base_loopexit(base, &delay);
}
// 定义标准的main函数
int main(int argc, char ** argv)
{
// event_base是整个event循环必要的结构体
struct event_base * base = event_base_new();
// 初始化sockaddr_in结构体,监听在0.0.0.0:9995
struct sockaddr_in sin;
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(PORT);
// bind在上面制定的IP和端口,同时初始化listen的事件循环和callback:listener_cb
// 并把listener的事件循环注册在event_base:base上
struct evconnlistener * listener = NULL;
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)
{
// 如果发生任何错误,向stderr(标准错误输出)打一条日志,退出
fprintf(stderr, "Could not create a listener!\n");
return 1;
}
#if 0
// 创建并初始化信号处理event
struct event *signal_event = evsignal_new(base, SIGINT, signal_cb, (void * )base);
//把这个callback放入base中
if (!signal_event || event_add(signal_event, NULL)<0)
{
fprintf(stderr, "Could not create/add a signal event!\n");
return 1;
}
#endif
// 程序将在下面这一行内启动event循环,只有在调用event_base_loopexit后
// 才会从下面这个函数返回,并向下执行各种清理函数,导致整个程序退出
event_base_dispatch(base);
// 各种清理free
evconnlistener_free(listener);
// event_free(signal_event);
event_base_free(base);
printf("done\n");
return 0;
}
0 0
- libevent_server 服务器程序详细注释
- s3c44b0初始化程序详细注释
- C# 解数独程序 注释详细
- win32窗口程序的详细注释
- 【详细注释】Java->Socket 服务器与客户端的半双工通讯。拥有详细注释,完美诠释。
- 微软ping程序源代码完整版(附详细的注释)
- 一个包含详细注释的portscan程序C源代码
- 微软ping程序源代码完整版(附详细的注释)
- 【转】微软ping程序源代码完整版(附详细的注释)
- 分析注释都非常详细的 c++ 入门程序
- 单词查询程序—《C++ primer 4》源代码详细注释
- HELLOWIN程序详细注释——《Windows程序设计》阅读笔记
- HELLOWIN程序详细注释——《Windows程序设计》阅读笔记
- [微信小程序]星级评分和展示(详细注释附效果图)
- 程序注释
- 程序注释
- 程序注释
- 程序注释
- hdu 2896 病毒侵袭 AC自动机入门题
- Java自定义注解
- Ubuntu16.04安装Anaconda2和Anaconda3
- 策略模式
- node-webkit制作桌面应用
- libevent_server 服务器程序详细注释
- Integer和int——Java包装器
- w未搞定的算法总结
- java-final关键字作用
- 基于Spring Boot和Cloud Foundry实现微服务架构学习(2017227更新)
- 关于SVD分解
- C语言
- 汉字编码(【Unicode】 【UTF-8】 【Unicode与UTF-8之间的转换】 【汉字 Unicode 编码范围】【中文标点Unicode码】【GBK编码】【批量获取汉字UNICODE码】)
- STL中map容器的几种插方法的区别