Libevent例子(一)
服务器端
- #include<stdio.h>
- #include<string.h>
- #include<errno.h>
- #include<event.h>
- #include<event2/bufferevent.h>
- void accept_cb(int fd, short events, void* arg);
- void socket_read_cb(bufferevent* bev, void* arg);
- void event_cb(struct bufferevent *bev, short event, void *arg);
- int tcp_server_init(int port, int listen_num);
- int main(int argc, char **argv) {
- int listener = tcp_server_init(, );
- if (listener == -) {
- perror(" tcp_server_init error ");
- return -;
- }
- struct event_base *base = event_base_new();
- //添加监听客户端请求连接事件
- struct event *ev_listen = event_new(
- base, listener, EV_READ | EV_PERSIST, accept_cb, base);
- event_add(ev_listen, NULL);
- event_base_dispatch(base);
- event_base_free(base);
- return ;
- }
- void accept_cb(int fd, short events, void *arg) {
- evutil_socket_t sockfd;
- struct sockaddr_in client;
- socklen_t len = sizeof(client);
- sockfd = accept(fd, (struct sockaddr *) &client, &len);
- evutil_make_socket_nonblocking(sockfd);
- printf("accept a client %d\n", sockfd);
- struct event_base *base = (struct event_base *) arg;
- bufferevent *bev = bufferevent_socket_new(base, sockfd, BEV_OPT_CLOSE_ON_FREE);
- bufferevent_setcb(bev, socket_read_cb, NULL, event_cb, arg);
- bufferevent_enable(bev, EV_READ | EV_PERSIST);
- }
- void socket_read_cb(bufferevent *bev, void *arg) {
- char msg[];
- size_t len = bufferevent_read(bev, msg, sizeof(msg));
- msg[len] = '\0';
- printf("recv the client msg: %s", msg);
- char reply_msg[] = "I have recvieced the msg: ";
- strcat(reply_msg + strlen(reply_msg), msg);
- bufferevent_write(bev, reply_msg, strlen(reply_msg));
- }
- void event_cb(struct bufferevent *bev, short event, void *arg) {
- if (event & BEV_EVENT_EOF) {
- printf("connection closed\n");
- }
- else if (event & BEV_EVENT_ERROR) {
- printf("some other error\n");
- }
- //这将自动close套接字和free读写缓冲区
- bufferevent_free(bev);
- }
- typedef struct sockaddr SA;
- int tcp_server_init(int port, int listen_num) {
- int errno_save;
- evutil_socket_t listener;
- listener = socket(AF_INET, SOCK_STREAM, );
- if (listener == -) {
- return -;
- }
- //允许多次绑定同一个地址。要用在socket和bind之间
- evutil_make_listen_socket_reuseable(listener);
- struct sockaddr_in sin;
- sin.sin_family = AF_INET;
- sin.sin_addr.s_addr = ;
- sin.sin_port = htons(port);
- if (bind(listener, (SA *) &sin, sizeof(sin)) < ) {
- goto error;
- }
- if (listen(listener, listen_num) < ) {
- goto error;
- }
- //跨平台统一接口,将套接字设置为非阻塞状态
- evutil_make_socket_nonblocking(listener);
- return listener;
- error:
- errno_save = errno;
- evutil_closesocket(listener);
- errno = errno_save;
- return -;
- }
客户端
- #include<sys/types.h>
- #include<sys/socket.h>
- #include<netinet/in.h>
- #include<arpa/inet.h>
- #include<errno.h>
- #include<unistd.h>
- #include<stdio.h>
- #include<string.h>
- #include<stdlib.h>
- #include<event.h>
- #include<event2/bufferevent.h>
- #include<event2/buffer.h>
- #include<event2/util.h>
- int tcp_connect_server(const char *server_ip, int port);
- void cmd_msg_cb(int fd, short events, void *arg);
- void server_msg_cb(struct bufferevent *bev, void *arg);
- void event_cb(struct bufferevent *bev, short event, void *arg);
- int main(int argc, char **argv) {
- if (argc < ) {
- printf("please input 2 parameter\n");
- return -;
- }
- //两个参数依次是服务器端的IP地址、端口号
- int sockfd = tcp_connect_server(argv[], atoi(argv[]));
- if (sockfd == -) {
- perror("tcp_connect error ");
- return -;
- }
- printf("connect to server successful\n");
- struct event_base *base = event_base_new();
- struct bufferevent *bev = bufferevent_socket_new(
- base, sockfd, BEV_OPT_CLOSE_ON_FREE);
- //监听终端输入事件
- struct event *ev_cmd = event_new(
- base, STDIN_FILENO, EV_READ | EV_PERSIST, cmd_msg_cb, (void *) bev);
- event_add(ev_cmd, NULL);
- //当socket关闭时会用到回调参数
- bufferevent_setcb(bev, server_msg_cb, NULL, event_cb, (void *) ev_cmd);
- bufferevent_enable(bev, EV_READ | EV_PERSIST);
- event_base_dispatch(base);
- printf("finished \n");
- return ;
- }
- void cmd_msg_cb(int fd, short events, void *arg) {
- char msg[];
- int ret = read(fd, msg, sizeof(msg));
- if (ret < ) {
- perror("read fail ");
- exit();
- }
- struct bufferevent *bev = (struct bufferevent *) arg;
- //把终端的消息发送给服务器端
- bufferevent_write(bev, msg, ret);
- }
- void server_msg_cb(struct bufferevent *bev, void *arg) {
- char msg[];
- size_t len = bufferevent_read(bev, msg, sizeof(msg));
- msg[len] = '\0';
- printf("recv %s from server\n", msg);
- }
- void event_cb(struct bufferevent *bev, short event, void *arg) {
- if (event & BEV_EVENT_EOF) {
- printf("connection closed\n");
- } else if (event & BEV_EVENT_ERROR) {
- printf("some other error\n");
- }
- //这将自动close套接字和free读写缓冲区
- bufferevent_free(bev);
- struct event *ev = (struct event *) arg;
- //因为socket已经没有,所以这个event也没有存在的必要了
- event_free(ev);
- }
- typedef struct sockaddr SA;
- int tcp_connect_server(const char *server_ip, int port) {
- int sockfd, status, save_errno;
- struct sockaddr_in server_addr;
- memset(&server_addr, , sizeof(server_addr));
- server_addr.sin_family = AF_INET;
- server_addr.sin_port = htons(port);
- status = inet_aton(server_ip, &server_addr.sin_addr);
- if (status == ) { //the server_ip is not valid value
- errno = EINVAL;
- return -;
- }
- sockfd = ::socket(PF_INET, SOCK_STREAM, );
- if (sockfd == -) {
- return sockfd;
- }
- status = ::connect(sockfd, (SA *) &server_addr, sizeof(server_addr));
- if (status == -) {
- save_errno = errno;
- ::close(sockfd);
- errno = save_errno; //the close may be error
- return -;
- }
- evutil_make_socket_nonblocking(sockfd);
- return sockfd;
- }
Libevent例子(一)的更多相关文章
- Libevent例子(二)
服务端 #include<netinet/in.h> #include<stdio.h> #include<string.h> #include<event. ...
- libevent学习总结
1. 信息隐藏:看*-internal.h文件 如bufferevent_private结构体在bufferevent_async.c中使用时: static inline struct buffer ...
- libevent源码分析:http-server例子
http-server例子是libevent提供的一个简单web服务器,实现了对静态网页的处理功能. /* * gcc -g -o http-server http-server.c -levent ...
- libevent源码分析:hello-world例子
hello-world是libevent自带的一个例子,这个例子的作用是启动后监听一个端口,对于所有通过这个端口连接上服务器的程序发送一段字符:hello-world,然后关闭连接. /* * gcc ...
- libevent源码分析:signal-test例子
signal-test是libevent自带的一个例子,展示了libevent对于信号事件的处理方法. #include <sys/types.h> #include <event2 ...
- libevent源码分析:time-test例子
time-test例子是libevent自带的一个例子,通过libevent提供的定时事件来实现,间隔固定时间打印的功能. /* * gcc -g -o time-test time-test.c - ...
- [z]Libevent使用例子,从简单到复杂
[z]http://blog.csdn.net/luotuo44/article/details/39670221 本文从简单到复杂,展示如何使用libevent.网上的许多例子都是只有服务器端的,本 ...
- Libevent学习笔记(五) 根据例子学习bufferevent
libevent中提供了一个Hello-world.c 的例子,从这个例子可以学习libevent是如何使用bufferevent的. 这个例子在Sample中 这个例子之前讲解过,这次主要看下buf ...
- 【Networking】Libevent客户端例子
[原]Libevent客户端例子 时间 -- :: luotuo44的专栏 原文 http://blog.csdn.net/luotuo44/article/details/34416429 主题 l ...
随机推荐
- Linux Command : top
top命令是Linux下常用的性能分析工具,能够实时显示系统中各个进程所占用的系统资源,类似于Windows的任务管理器.下面详细介绍它的使用方法.top是一个动态显示过程,即可以通过用户按键来不断刷 ...
- JavaScript:String 对象
ylbtech-JavaScript:String 对象 1.返回顶部 String 对象 String 对象用于处理文本(字符串). 创建 String 对象的语法: new String(s); ...
- C++ assert 断言使用
在研究corepattern需要让程序出core, 因此用到的assert, 记录一下. 写严谨代码时,也可以使用assert进行严格的条件判断. 函数原型: #include <asser ...
- go语言之进阶篇无缓冲channel
1.无缓冲channel 示例: package main import ( "fmt" "time" ) func main() { //创建一个无缓存的ch ...
- 算法 数组中出现次数最多的数字 MD
Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...
- windows及linux环境下永久修改pip镜像源的方法
一.在windows环境下修改pip镜像源的方法(以python3.5为例) (1):在windows文件管理器中,输入 %APPDATA% (2):会定位到一个新的目录下,在该目录下新建pip文件夹 ...
- nodejs pipe实现大文件拷贝
原文: http://nqdeng.github.io/7-days-nodejs/ --------------------------------------------------------- ...
- 火星坐标、百度坐标、WGS84坐标转换代码(JS、python版)
火星坐标.百度坐标.WGS84坐标转换代码(JS.python版) 一.JS版本源码 github:https://github.com/wandergis/coordTransform /** * ...
- 解决Android sdk无法下载的问题
由于android官网在国内无法正常访问,在安装android sdk时经常会出现http://dl.google.com拒绝访问的情况.为了解决这个问题,建议使用国内镜像源,这里推荐几个: 1.mi ...
- 前端特效: 使用CSS生成的闪光照相机效果
使用纯CSS生成的照相机效果, 相关CSS代码如下: .container { position: absolute; top: 50%; left: 50%; -webkit-transform: ...