服务器端

#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例子(一)的更多相关文章

  1. Libevent例子(二)

    服务端 #include<netinet/in.h> #include<stdio.h> #include<string.h> #include<event. ...

  2. libevent学习总结

    1. 信息隐藏:看*-internal.h文件 如bufferevent_private结构体在bufferevent_async.c中使用时: static inline struct buffer ...

  3. libevent源码分析:http-server例子

    http-server例子是libevent提供的一个简单web服务器,实现了对静态网页的处理功能. /* * gcc -g -o http-server http-server.c -levent ...

  4. libevent源码分析:hello-world例子

    hello-world是libevent自带的一个例子,这个例子的作用是启动后监听一个端口,对于所有通过这个端口连接上服务器的程序发送一段字符:hello-world,然后关闭连接. /* * gcc ...

  5. libevent源码分析:signal-test例子

    signal-test是libevent自带的一个例子,展示了libevent对于信号事件的处理方法. #include <sys/types.h> #include <event2 ...

  6. libevent源码分析:time-test例子

    time-test例子是libevent自带的一个例子,通过libevent提供的定时事件来实现,间隔固定时间打印的功能. /* * gcc -g -o time-test time-test.c - ...

  7. [z]Libevent使用例子,从简单到复杂

    [z]http://blog.csdn.net/luotuo44/article/details/39670221 本文从简单到复杂,展示如何使用libevent.网上的许多例子都是只有服务器端的,本 ...

  8. Libevent学习笔记(五) 根据例子学习bufferevent

    libevent中提供了一个Hello-world.c 的例子,从这个例子可以学习libevent是如何使用bufferevent的. 这个例子在Sample中 这个例子之前讲解过,这次主要看下buf ...

  9. 【Networking】Libevent客户端例子

    [原]Libevent客户端例子 时间 -- :: luotuo44的专栏 原文 http://blog.csdn.net/luotuo44/article/details/34416429 主题 l ...

随机推荐

  1. SQLSERVER系统视图 sql server系统表详细说明

    参考 https://www.cnblogs.com/luluping/archive/2012/11/05/2754639.html https://www.cnblogs.com/litubin/ ...

  2. 回顾 Exchange 2007 SCC 安装-供需要的人参考!

    最近可能会涉及到一个项目的升级,客户目前是基于SCC+SCR的一种工作模式,因为之前对SCR 了解很少,所以需要搭建一个SCC+SCR 平台来做一个整体的POC,来还原整个安装和升级过程. 首先我们先 ...

  3. maven-assembly-plugin 入门指南

    当你使用 Maven 对项目打包时,你需要了解以下 3 个打包 plugin,它们分别是 plugin function maven-jar-plugin maven 默认打包插件,用来创建 proj ...

  4. jstorm简介

    最近在研究jstorm,看了很多资料,所以也想分享出来一些. 安装部署 zeromq 简单快速的传输层框架,安装如下: wget http://download.zeromq.org/zeromq-2 ...

  5. jquery实现上传文件大小类型的验证

    <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...

  6. 插件化 VirtualAPK 简介 体验 MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...

  7. virtualBox导入虚拟机启动报错

    今天使用Oracle VMbox在导入虚拟机后,启动时报了如下错误: A new node couldn't be inserted because one with the same name ex ...

  8. mac 安装 RabbitMQ

    https://blog.csdn.net/u010046908/article/details/54773323

  9. C#.NET常见问题(FAQ)-如何使用2D绘图控件ZedGraph绘制坐标轴和坐标曲线

    添加数据:示例添加了一条sin曲线和一条cos曲线,注意cos曲线比sin曲线点更密集(可以用这种方式控制点的采样疏密程度)   默认显示效果如下图所示,可以框选一个部分看放大效果   右击某个点可以 ...

  10. C语言处理文件

    C写入数据到文件 #include <stdio.h> #include <string.h> int main( ) { FILE* fd = fopen("txt ...