【Networking】Libevent客户端例子
- [原]Libevent客户端例子
- 时间 -- :: luotuo44的专栏
- 原文 http://blog.csdn.net/luotuo44/article/details/34416429
- 主题 libevent Socket
- 网上关于Libevent的例子大多数都是服务器端的例子,我写一个客户端例子和大家分享。不多说了,上代码。
- #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 error_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);
- bufferevent_setcb(bev, server_msg_cb, NULL, error_cb, NULL);
- bufferevent_enable(bev, EV_READ | EV_PERSIST);
- //监听终端输入事件
- struct event* ev_cmd = event_new(base, STDIN_FILENO,
- EV_READ | EV_PERSIST, cmd_msg_cb,
- (void*)bev);
- event_add(ev_cmd, NULL);
- 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 error_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_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;
- }
- 在main函数里面,要先connect上服务器,然后用套接字作为参数,新建一个struct buffereven。
- 我试过像下面这样写
- struct bufferevent* bev = bufferevent_socket_new(base, -,
- BEV_OPT_CLOSE_ON_FREE);
- if( bev == NULL)
- {
- printf("bufferevent_socket_new fail\n");
- return -;
- }
- struct sockaddr_in server_addr;
- memset(&server_addr, , sizeof(server_addr) );
- server_addr.sin_family = AF_INET;
- server_addr.sin_port = htons(atoi(argv[]));
- int status = inet_aton(argv[], &server_addr.sin_addr);
- int sockfd = bufferevent_socket_connect(bev, (struct sockaddr *)&server_addr,
- sizeof(server_addr));
- 即通过bufferevent_socket_connect函数来获取一个连接上服务器的套接字。但总会一连上服务器端,sockfd就关闭了。
- 下面是对应服务器端的例子。
- #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 error_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);
- return ;
- }
- void accept_cb(int fd, short events, void* arg)
- {
- evutil_socket_t sockfd;
- struct sockaddr_in client;
- socklen_t len;
- sockfd = ::accept(fd, (struct sockaddr*)&client, &len );
- evutil_make_socket_nonblocking(sockfd);
- printf("accept a client %d\n", sockfd);
- struct event_base* base = (event_base*)arg;
- bufferevent* bev = bufferevent_socket_new(base, sockfd, BEV_OPT_CLOSE_ON_FREE);
- bufferevent_setcb(bev, socket_read_cb, NULL, error_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 error_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 -;
- }
参考资料:
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客户端例子的更多相关文章
- [z]Libevent使用例子,从简单到复杂
[z]http://blog.csdn.net/luotuo44/article/details/39670221 本文从简单到复杂,展示如何使用libevent.网上的许多例子都是只有服务器端的,本 ...
- Libevent使用例子,从简单到复杂
转载请注明出处:http://blog.csdn.net/luotuo44/article/details/39670221 本文从简单到复杂,展示如何使用libevent.网上的许多例子都是只有服务 ...
- webservice 服务端例子+客户端例子+CXF整合spring服务端测试+生成wsdl文件 +cxf客户端代码自动生成
首先到CXF官网及spring官网下载相关jar架包,这个不多说.webservice是干嘛用的也不多说. 入门例子 模拟新增一个用户,并返回新增结果,成功还是失败. 大概的目录如上,很简单. Res ...
- 网络(一),libevent客户端部分
网络模块() 一.服务端: 暂时就以libevent模块,共享内存等下 .GS打开,首先创建4个libevent子线程,当然为每个线程设置连接通知回调函数,这个是基于sockpair的,然后再创建一个 ...
- 基于H7的串口WIFI模块ESP8266的TCP客户端例子和操作说明(AP兼STA模式)
说明: 1.如果不熟悉网络的话,等我这几天更新V7用户手册的ESP8266章节,如果熟悉的话,直接操作即可,这里将操作说明发出来. 2.串口WIFI是采用的AT指令操作,简单易用,指令手册在这个帖子里 ...
- Libevent使用例子
初等: 客户端代码: #include<sys/types.h> #include<sys/socket.h> #include<netinet/in.h> #in ...
- c++ tcp 服务器和客户端例子
目标: 完成一个精简TCP服务器,可接收来自多个用户的请求,并返回结果. 思路: (1)服务器 C++ TCP服务器的实现主要由以下几个函数来完成: a)socket ...
- delphpi tcp 服务和客户端 例子
//服务器端unit Unit1; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, ...
- libevent编程疑难解答
http://blog.csdn.net/luotuo44/article/details/39547391 转载请注明出处:http://blog.csdn.net/luotuo44/article ...
随机推荐
- 【WPF】Bitmap Effect制作圆角加渲染TextBox
<Window.Resources> <ControlTemplate x:Key="txtTemplate" TargetType="{x:Type ...
- 【伪暴力+智商剪枝】Codeforces Round #489 (Div. 2) D
失踪人口突然回归……orz.题解还是有必要写的,虽然估计只有自己(?自己也不一定看得懂)看得懂. 题目链接:http://codeforces.com/contest/992/problem/D 题目 ...
- 关于 DP 的一些题目
DP 是真的好玩. 口胡一段话题解: DP 题集 1 DP 题集 2
- brpc初探
因为最近在看一个内部开源代码,看到了braft.braft又依赖于brpc.于是就看了相关的文档,打算接下来试一把. 这里引用下gejun大佬在知乎上的回答(https://www.zhihu.com ...
- redis_安装
前面几章内容简单介绍了NoSql的概念,以及NoSql的几种分类,本文开始后面开始学习KV数据库Redis. 一.Redis是什么? Redis:REmote DIctionary Server(远程 ...
- android 传递 类对象 序列化 Serializable
public class Song implements Serializable { /** * */ private static final long serialVersionUID = 64 ...
- 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] ...
- [CCC 2018] 平衡树
题面在这里! 根据题目描述就可以直接模拟出一个暴力. 如果把前 n^(1/2) 的树的方案数先一遍 O(n^(3/4)) 暴力预处理出来(其实复杂度并到不了这个级别),然后把n带进来直接暴力算就行了. ...
- OpenSSL Heartbleed “心脏滴血”漏洞简单攻击示例
OpenSSL Heartbleed漏洞的公开和流行让许多人兴奋了一把,也让另一些人惊慌了一把. 单纯从攻击的角度讲,我已知道的,网上公开的扫描工具有: 1. Nmap脚本ssl-heartblee ...
- Java解释执行和编译执行
以前有句话说:“Java是解释执行的 ” .现在看来确实不是很准确,至于原因,在此简略解释: 首先,我们先解释一下在Java中解释执行和编译执行的区别. 解释执行:将编译好的字节码一行一行地翻译为机器 ...