服务器端

  1. #include<stdio.h>
  2. #include<string.h>
  3. #include<errno.h>
  4. #include<event.h>
  5. #include<event2/bufferevent.h>
  6.  
  7. void accept_cb(int fd, short events, void* arg);
  8. void socket_read_cb(bufferevent* bev, void* arg);
  9. void event_cb(struct bufferevent *bev, short event, void *arg);
  10. int tcp_server_init(int port, int listen_num);
  11.  
  12. int main(int argc, char **argv) {
  13.  
  14. int listener = tcp_server_init(, );
  15. if (listener == -) {
  16. perror(" tcp_server_init error ");
  17. return -;
  18. }
  19. struct event_base *base = event_base_new();
  20. //添加监听客户端请求连接事件
  21. struct event *ev_listen = event_new(
  22. base, listener, EV_READ | EV_PERSIST, accept_cb, base);
  23. event_add(ev_listen, NULL);
  24. event_base_dispatch(base);
  25. event_base_free(base);
  26. return ;
  27. }
  28.  
  29. void accept_cb(int fd, short events, void *arg) {
  30. evutil_socket_t sockfd;
  31. struct sockaddr_in client;
  32. socklen_t len = sizeof(client);
  33. sockfd = accept(fd, (struct sockaddr *) &client, &len);
  34. evutil_make_socket_nonblocking(sockfd);
  35. printf("accept a client %d\n", sockfd);
  36. struct event_base *base = (struct event_base *) arg;
  37. bufferevent *bev = bufferevent_socket_new(base, sockfd, BEV_OPT_CLOSE_ON_FREE);
  38. bufferevent_setcb(bev, socket_read_cb, NULL, event_cb, arg);
  39. bufferevent_enable(bev, EV_READ | EV_PERSIST);
  40. }
  41.  
  42. void socket_read_cb(bufferevent *bev, void *arg) {
  43. char msg[];
  44. size_t len = bufferevent_read(bev, msg, sizeof(msg));
  45. msg[len] = '\0';
  46. printf("recv the client msg: %s", msg);
  47. char reply_msg[] = "I have recvieced the msg: ";
  48. strcat(reply_msg + strlen(reply_msg), msg);
  49. bufferevent_write(bev, reply_msg, strlen(reply_msg));
  50. }
  51.  
  52. void event_cb(struct bufferevent *bev, short event, void *arg) {
  53.  
  54. if (event & BEV_EVENT_EOF) {
  55. printf("connection closed\n");
  56. }
  57. else if (event & BEV_EVENT_ERROR) {
  58. printf("some other error\n");
  59. }
  60. //这将自动close套接字和free读写缓冲区
  61. bufferevent_free(bev);
  62. }
  63.  
  64. typedef struct sockaddr SA;
  65.  
  66. int tcp_server_init(int port, int listen_num) {
  67. int errno_save;
  68. evutil_socket_t listener;
  69.  
  70. listener = socket(AF_INET, SOCK_STREAM, );
  71. if (listener == -) {
  72. return -;
  73. }
  74.  
  75. //允许多次绑定同一个地址。要用在socket和bind之间
  76. evutil_make_listen_socket_reuseable(listener);
  77.  
  78. struct sockaddr_in sin;
  79. sin.sin_family = AF_INET;
  80. sin.sin_addr.s_addr = ;
  81. sin.sin_port = htons(port);
  82.  
  83. if (bind(listener, (SA *) &sin, sizeof(sin)) < ) {
  84. goto error;
  85. }
  86. if (listen(listener, listen_num) < ) {
  87. goto error;
  88. }
  89.  
  90. //跨平台统一接口,将套接字设置为非阻塞状态
  91. evutil_make_socket_nonblocking(listener);
  92. return listener;
  93.  
  94. error:
  95. errno_save = errno;
  96. evutil_closesocket(listener);
  97. errno = errno_save;
  98. return -;
  99. }

客户端

  1. #include<sys/types.h>
  2. #include<sys/socket.h>
  3. #include<netinet/in.h>
  4. #include<arpa/inet.h>
  5. #include<errno.h>
  6. #include<unistd.h>
  7. #include<stdio.h>
  8. #include<string.h>
  9. #include<stdlib.h>
  10. #include<event.h>
  11. #include<event2/bufferevent.h>
  12. #include<event2/buffer.h>
  13. #include<event2/util.h>
  14.  
  15. int tcp_connect_server(const char *server_ip, int port);
  16.  
  17. void cmd_msg_cb(int fd, short events, void *arg);
  18.  
  19. void server_msg_cb(struct bufferevent *bev, void *arg);
  20.  
  21. void event_cb(struct bufferevent *bev, short event, void *arg);
  22.  
  23. int main(int argc, char **argv) {
  24. if (argc < ) {
  25. printf("please input 2 parameter\n");
  26. return -;
  27. }
  28.  
  29. //两个参数依次是服务器端的IP地址、端口号
  30. int sockfd = tcp_connect_server(argv[], atoi(argv[]));
  31. if (sockfd == -) {
  32. perror("tcp_connect error ");
  33. return -;
  34. }
  35.  
  36. printf("connect to server successful\n");
  37. struct event_base *base = event_base_new();
  38. struct bufferevent *bev = bufferevent_socket_new(
  39. base, sockfd, BEV_OPT_CLOSE_ON_FREE);
  40.  
  41. //监听终端输入事件
  42. struct event *ev_cmd = event_new(
  43. base, STDIN_FILENO, EV_READ | EV_PERSIST, cmd_msg_cb, (void *) bev);
  44. event_add(ev_cmd, NULL);
  45.  
  46. //当socket关闭时会用到回调参数
  47. bufferevent_setcb(bev, server_msg_cb, NULL, event_cb, (void *) ev_cmd);
  48. bufferevent_enable(bev, EV_READ | EV_PERSIST);
  49. event_base_dispatch(base);
  50. printf("finished \n");
  51. return ;
  52. }
  53.  
  54. void cmd_msg_cb(int fd, short events, void *arg) {
  55. char msg[];
  56.  
  57. int ret = read(fd, msg, sizeof(msg));
  58. if (ret < ) {
  59. perror("read fail ");
  60. exit();
  61. }
  62.  
  63. struct bufferevent *bev = (struct bufferevent *) arg;
  64. //把终端的消息发送给服务器端
  65. bufferevent_write(bev, msg, ret);
  66. }
  67.  
  68. void server_msg_cb(struct bufferevent *bev, void *arg) {
  69. char msg[];
  70. size_t len = bufferevent_read(bev, msg, sizeof(msg));
  71. msg[len] = '\0';
  72. printf("recv %s from server\n", msg);
  73. }
  74.  
  75. void event_cb(struct bufferevent *bev, short event, void *arg) {
  76.  
  77. if (event & BEV_EVENT_EOF) {
  78. printf("connection closed\n");
  79. } else if (event & BEV_EVENT_ERROR) {
  80. printf("some other error\n");
  81. }
  82. //这将自动close套接字和free读写缓冲区
  83. bufferevent_free(bev);
  84. struct event *ev = (struct event *) arg;
  85. //因为socket已经没有,所以这个event也没有存在的必要了
  86. event_free(ev);
  87. }
  88.  
  89. typedef struct sockaddr SA;
  90.  
  91. int tcp_connect_server(const char *server_ip, int port) {
  92. int sockfd, status, save_errno;
  93. struct sockaddr_in server_addr;
  94.  
  95. memset(&server_addr, , sizeof(server_addr));
  96.  
  97. server_addr.sin_family = AF_INET;
  98. server_addr.sin_port = htons(port);
  99. status = inet_aton(server_ip, &server_addr.sin_addr);
  100.  
  101. if (status == ) { //the server_ip is not valid value
  102. errno = EINVAL;
  103. return -;
  104. }
  105.  
  106. sockfd = ::socket(PF_INET, SOCK_STREAM, );
  107. if (sockfd == -) {
  108. return sockfd;
  109. }
  110. status = ::connect(sockfd, (SA *) &server_addr, sizeof(server_addr));
  111. if (status == -) {
  112. save_errno = errno;
  113. ::close(sockfd);
  114. errno = save_errno; //the close may be error
  115. return -;
  116. }
  117. evutil_make_socket_nonblocking(sockfd);
  118. return sockfd;
  119. }

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. Linux Command : top

    top命令是Linux下常用的性能分析工具,能够实时显示系统中各个进程所占用的系统资源,类似于Windows的任务管理器.下面详细介绍它的使用方法.top是一个动态显示过程,即可以通过用户按键来不断刷 ...

  2. JavaScript:String 对象

    ylbtech-JavaScript:String 对象 1.返回顶部 String 对象 String 对象用于处理文本(字符串). 创建 String 对象的语法: new String(s); ...

  3. C++ assert 断言使用

    在研究corepattern需要让程序出core, 因此用到的assert, 记录一下. 写严谨代码时,也可以使用assert进行严格的条件判断.   函数原型: #include <asser ...

  4. go语言之进阶篇无缓冲channel

    1.无缓冲channel 示例: package main import ( "fmt" "time" ) func main() { //创建一个无缓存的ch ...

  5. 算法 数组中出现次数最多的数字 MD

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

  6. windows及linux环境下永久修改pip镜像源的方法

    一.在windows环境下修改pip镜像源的方法(以python3.5为例) (1):在windows文件管理器中,输入 %APPDATA% (2):会定位到一个新的目录下,在该目录下新建pip文件夹 ...

  7. nodejs pipe实现大文件拷贝

    原文: http://nqdeng.github.io/7-days-nodejs/ --------------------------------------------------------- ...

  8. 火星坐标、百度坐标、WGS84坐标转换代码(JS、python版)

    火星坐标.百度坐标.WGS84坐标转换代码(JS.python版) 一.JS版本源码 github:https://github.com/wandergis/coordTransform /** * ...

  9. 解决Android sdk无法下载的问题

    由于android官网在国内无法正常访问,在安装android sdk时经常会出现http://dl.google.com拒绝访问的情况.为了解决这个问题,建议使用国内镜像源,这里推荐几个: 1.mi ...

  10. 前端特效: 使用CSS生成的闪光照相机效果

    使用纯CSS生成的照相机效果, 相关CSS代码如下: .container { position: absolute; top: 50%; left: 50%; -webkit-transform: ...