1. [原]Libevent客户端例子
  2. 时间 -- :: luotuo44的专栏
  3. 原文 http://blog.csdn.net/luotuo44/article/details/34416429
  4. 主题 libevent Socket
  5. 网上关于Libevent的例子大多数都是服务器端的例子,我写一个客户端例子和大家分享。不多说了,上代码。
  6.  
  7. #include<sys/types.h>
  8. #include<sys/socket.h>
  9. #include<netinet/in.h>
  10. #include<arpa/inet.h>
  11. #include<errno.h>
  12. #include<unistd.h>
  13.  
  14. #include<stdio.h>
  15. #include<string.h>
  16. #include<stdlib.h>
  17.  
  18. #include<event.h>
  19. #include<event2/bufferevent.h>
  20. #include<event2/buffer.h>
  21. #include<event2/util.h>
  22.  
  23. int tcp_connect_server(const char* server_ip, int port);
  24.  
  25. void cmd_msg_cb(int fd, short events, void* arg);
  26. void server_msg_cb(struct bufferevent* bev, void* arg);
  27. void error_cb(struct bufferevent *bev, short event, void *arg);
  28.  
  29. int main(int argc, char** argv)
  30. {
  31. if( argc < )
  32. {
  33. printf("please input 2 parameter\n");
  34. return -;
  35. }
  36.  
  37. //两个参数依次是服务器端的IP地址、端口号
  38. int sockfd = tcp_connect_server(argv[], atoi(argv[]));
  39. if( sockfd == -)
  40. {
  41. perror("tcp_connect error ");
  42. return -;
  43. }
  44.  
  45. printf("connect to server successful\n");
  46.  
  47. struct event_base* base = event_base_new();
  48.  
  49. struct bufferevent* bev = bufferevent_socket_new(base, sockfd,
  50. BEV_OPT_CLOSE_ON_FREE);
  51. bufferevent_setcb(bev, server_msg_cb, NULL, error_cb, NULL);
  52. bufferevent_enable(bev, EV_READ | EV_PERSIST);
  53.  
  54. //监听终端输入事件
  55. struct event* ev_cmd = event_new(base, STDIN_FILENO,
  56. EV_READ | EV_PERSIST, cmd_msg_cb,
  57. (void*)bev);
  58.  
  59. event_add(ev_cmd, NULL);
  60.  
  61. event_base_dispatch(base);
  62.  
  63. printf("finished \n");
  64. return ;
  65. }
  66.  
  67. void cmd_msg_cb(int fd, short events, void* arg)
  68. {
  69. char msg[];
  70.  
  71. int ret = read(fd, msg, sizeof(msg));
  72. if( ret < )
  73. {
  74. perror("read fail ");
  75. exit();
  76. }
  77.  
  78. struct bufferevent* bev = (struct bufferevent*)arg;
  79.  
  80. //把终端的消息发送给服务器端
  81. bufferevent_write(bev, msg, ret);
  82. }
  83.  
  84. void server_msg_cb(struct bufferevent* bev, void* arg)
  85. {
  86. char msg[];
  87.  
  88. size_t len = bufferevent_read(bev, msg, sizeof(msg));
  89. msg[len] = '\0';
  90.  
  91. printf("recv %s from server\n", msg);
  92. }
  93.  
  94. void error_cb(struct bufferevent *bev, short event, void *arg)
  95. {
  96.  
  97. if (event & BEV_EVENT_EOF)
  98. printf("connection closed\n");
  99. else if (event & BEV_EVENT_ERROR)
  100. printf("some other error\n");
  101.  
  102. //这将自动close套接字和free读写缓冲区
  103. bufferevent_free(bev);
  104. }
  105.  
  106. typedef struct sockaddr SA;
  107. int tcp_connect_server(const char* server_ip, int port)
  108. {
  109. int sockfd, status, save_errno;
  110. struct sockaddr_in server_addr;
  111.  
  112. memset(&server_addr, , sizeof(server_addr) );
  113.  
  114. server_addr.sin_family = AF_INET;
  115. server_addr.sin_port = htons(port);
  116. status = inet_aton(server_ip, &server_addr.sin_addr);
  117.  
  118. if( status == ) //the server_ip is not valid value
  119. {
  120. errno = EINVAL;
  121. return -;
  122. }
  123.  
  124. sockfd = ::socket(PF_INET, SOCK_STREAM, );
  125. if( sockfd == - )
  126. return sockfd;
  127.  
  128. status = ::connect(sockfd, (SA*)&server_addr, sizeof(server_addr) );
  129.  
  130. if( status == - )
  131. {
  132. save_errno = errno;
  133. ::close(sockfd);
  134. errno = save_errno; //the close may be error
  135. return -;
  136. }
  137.  
  138. evutil_make_socket_nonblocking(sockfd);
  139.  
  140. return sockfd;
  141. }
  142. main函数里面,要先connect上服务器,然后用套接字作为参数,新建一个struct buffereven
  143.  
  144. 我试过像下面这样写
  145.  
  146. struct bufferevent* bev = bufferevent_socket_new(base, -,
  147. BEV_OPT_CLOSE_ON_FREE);
  148. if( bev == NULL)
  149. {
  150. printf("bufferevent_socket_new fail\n");
  151. return -;
  152. }
  153.  
  154. struct sockaddr_in server_addr;
  155.  
  156. memset(&server_addr, , sizeof(server_addr) );
  157.  
  158. server_addr.sin_family = AF_INET;
  159. server_addr.sin_port = htons(atoi(argv[]));
  160. int status = inet_aton(argv[], &server_addr.sin_addr);
  161.  
  162. int sockfd = bufferevent_socket_connect(bev, (struct sockaddr *)&server_addr,
  163. sizeof(server_addr));
  164. 即通过bufferevent_socket_connect函数来获取一个连接上服务器的套接字。但总会一连上服务器端,sockfd就关闭了。
  165.  
  166. 下面是对应服务器端的例子。
  167.  
  168. #include<stdio.h>
  169. #include<string.h>
  170. #include<errno.h>
  171.  
  172. #include<event.h>
  173. #include<event2/bufferevent.h>
  174.  
  175. void accept_cb(int fd, short events, void* arg);
  176. void socket_read_cb(bufferevent* bev, void* arg);
  177. void error_cb(struct bufferevent *bev, short event, void *arg);
  178. int tcp_server_init(int port, int listen_num);
  179.  
  180. int main(int argc, char** argv)
  181. {
  182.  
  183. int listener = tcp_server_init(, );
  184. if( listener == - )
  185. {
  186. perror(" tcp_server_init error ");
  187. return -;
  188. }
  189.  
  190. struct event_base* base = event_base_new();
  191.  
  192. //添加监听客户端请求连接事件
  193. struct event* ev_listen = event_new(base, listener, EV_READ | EV_PERSIST,
  194. accept_cb, base);
  195. event_add(ev_listen, NULL);
  196.  
  197. event_base_dispatch(base);
  198.  
  199. return ;
  200. }
  201.  
  202. void accept_cb(int fd, short events, void* arg)
  203. {
  204. evutil_socket_t sockfd;
  205.  
  206. struct sockaddr_in client;
  207. socklen_t len;
  208.  
  209. sockfd = ::accept(fd, (struct sockaddr*)&client, &len );
  210. evutil_make_socket_nonblocking(sockfd);
  211.  
  212. printf("accept a client %d\n", sockfd);
  213.  
  214. struct event_base* base = (event_base*)arg;
  215.  
  216. bufferevent* bev = bufferevent_socket_new(base, sockfd, BEV_OPT_CLOSE_ON_FREE);
  217. bufferevent_setcb(bev, socket_read_cb, NULL, error_cb, arg);
  218.  
  219. bufferevent_enable(bev, EV_READ | EV_PERSIST);
  220. }
  221.  
  222. void socket_read_cb(bufferevent* bev, void* arg)
  223. {
  224. char msg[];
  225.  
  226. size_t len = bufferevent_read(bev, msg, sizeof(msg));
  227.  
  228. msg[len] = '\0';
  229. printf("recv the client msg: %s", msg);
  230.  
  231. char reply_msg[] = "I have recvieced the msg: ";
  232.  
  233. strcat(reply_msg + strlen(reply_msg), msg);
  234. bufferevent_write(bev, reply_msg, strlen(reply_msg));
  235. }
  236.  
  237. void error_cb(struct bufferevent *bev, short event, void *arg)
  238. {
  239.  
  240. if (event & BEV_EVENT_EOF)
  241. printf("connection closed\n");
  242. else if (event & BEV_EVENT_ERROR)
  243. printf("some other error\n");
  244.  
  245. //这将自动close套接字和free读写缓冲区
  246. bufferevent_free(bev);
  247. }
  248.  
  249. typedef struct sockaddr SA;
  250. int tcp_server_init(int port, int listen_num)
  251. {
  252. int errno_save;
  253. evutil_socket_t listener;
  254.  
  255. listener = ::socket(AF_INET, SOCK_STREAM, );
  256. if( listener == - )
  257. return -;
  258.  
  259. //允许多次绑定同一个地址。要用在socket和bind之间
  260. evutil_make_listen_socket_reuseable(listener);
  261.  
  262. struct sockaddr_in sin;
  263. sin.sin_family = AF_INET;
  264. sin.sin_addr.s_addr = ;
  265. sin.sin_port = htons(port);
  266.  
  267. if( ::bind(listener, (SA*)&sin, sizeof(sin)) < )
  268. goto error;
  269.  
  270. if( ::listen(listener, listen_num) < )
  271. goto error;
  272.  
  273. //跨平台统一接口,将套接字设置为非阻塞状态
  274. evutil_make_socket_nonblocking(listener);
  275.  
  276. return listener;
  277.  
  278. error:
  279. errno_save = errno;
  280. evutil_closesocket(listener);
  281. errno = errno_save;
  282.  
  283. return -;
  284. }

参考资料:

http://www.tuicool.com/articles/uuQvai

http://blog.csdn.net/nanjunxiao/article/details/9066077

http://blog.csdn.net/lulyon/article/details/51259109

http://cnodejs.org/topic/506d524c01d0b80148be69d8

https://www.zhihu.com/question/20278441

【Networking】Libevent客户端例子的更多相关文章

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

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

  2. Libevent使用例子,从简单到复杂

    转载请注明出处:http://blog.csdn.net/luotuo44/article/details/39670221 本文从简单到复杂,展示如何使用libevent.网上的许多例子都是只有服务 ...

  3. webservice 服务端例子+客户端例子+CXF整合spring服务端测试+生成wsdl文件 +cxf客户端代码自动生成

    首先到CXF官网及spring官网下载相关jar架包,这个不多说.webservice是干嘛用的也不多说. 入门例子 模拟新增一个用户,并返回新增结果,成功还是失败. 大概的目录如上,很简单. Res ...

  4. 网络(一),libevent客户端部分

    网络模块() 一.服务端: 暂时就以libevent模块,共享内存等下 .GS打开,首先创建4个libevent子线程,当然为每个线程设置连接通知回调函数,这个是基于sockpair的,然后再创建一个 ...

  5. 基于H7的串口WIFI模块ESP8266的TCP客户端例子和操作说明(AP兼STA模式)

    说明: 1.如果不熟悉网络的话,等我这几天更新V7用户手册的ESP8266章节,如果熟悉的话,直接操作即可,这里将操作说明发出来. 2.串口WIFI是采用的AT指令操作,简单易用,指令手册在这个帖子里 ...

  6. Libevent使用例子

    初等: 客户端代码: #include<sys/types.h> #include<sys/socket.h> #include<netinet/in.h> #in ...

  7. c++ tcp 服务器和客户端例子

    目标:  完成一个精简TCP服务器,可接收来自多个用户的请求,并返回结果. 思路:  (1)服务器      C++ TCP服务器的实现主要由以下几个函数来完成:        a)socket    ...

  8. delphpi tcp 服务和客户端 例子

    //服务器端unit Unit1; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, ...

  9. libevent编程疑难解答

    http://blog.csdn.net/luotuo44/article/details/39547391 转载请注明出处:http://blog.csdn.net/luotuo44/article ...

随机推荐

  1. 【WPF】Bitmap Effect制作圆角加渲染TextBox

    <Window.Resources> <ControlTemplate x:Key="txtTemplate" TargetType="{x:Type ...

  2. 【伪暴力+智商剪枝】Codeforces Round #489 (Div. 2) D

    失踪人口突然回归……orz.题解还是有必要写的,虽然估计只有自己(?自己也不一定看得懂)看得懂. 题目链接:http://codeforces.com/contest/992/problem/D 题目 ...

  3. 关于 DP 的一些题目

    DP 是真的好玩. 口胡一段话题解: DP 题集 1 DP 题集 2

  4. brpc初探

    因为最近在看一个内部开源代码,看到了braft.braft又依赖于brpc.于是就看了相关的文档,打算接下来试一把. 这里引用下gejun大佬在知乎上的回答(https://www.zhihu.com ...

  5. redis_安装

    前面几章内容简单介绍了NoSql的概念,以及NoSql的几种分类,本文开始后面开始学习KV数据库Redis. 一.Redis是什么? Redis:REmote DIctionary Server(远程 ...

  6. android 传递 类对象 序列化 Serializable

    public class Song implements Serializable { /** * */ private static final long serialVersionUID = 64 ...

  7. Wannafly挑战赛17 B

    题解 大概就是求证这个 \[\sum_i^nC_{n}^i*C_n^i = C_{2n}^n\] 证明: \[(1+x)^{2n} = [C(0,n)+C(1,n)*x+...+C(n,n)*x^n] ...

  8. [CCC 2018] 平衡树

    题面在这里! 根据题目描述就可以直接模拟出一个暴力. 如果把前 n^(1/2) 的树的方案数先一遍 O(n^(3/4)) 暴力预处理出来(其实复杂度并到不了这个级别),然后把n带进来直接暴力算就行了. ...

  9. OpenSSL Heartbleed “心脏滴血”漏洞简单攻击示例

    OpenSSL Heartbleed漏洞的公开和流行让许多人兴奋了一把,也让另一些人惊慌了一把. 单纯从攻击的角度讲,我已知道的,网上公开的扫描工具有: 1.  Nmap脚本ssl-heartblee ...

  10. Java解释执行和编译执行

    以前有句话说:“Java是解释执行的 ” .现在看来确实不是很准确,至于原因,在此简略解释: 首先,我们先解释一下在Java中解释执行和编译执行的区别. 解释执行:将编译好的字节码一行一行地翻译为机器 ...