【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 ...
随机推荐
- ls 大全
ls命令是linux下最常用的命令.ls命令就是list的缩写缺省下ls用来打印出当前目录的清单如果ls指定其他目录那么就会显示指定目录里的文件及文件夹清单. 通过ls 命令不仅可以查看linu ...
- 【centos 7】搭FTP服务和web访问
步骤:安装 vsftpd-->增加用户-->配置vsftpd和用户权限 -->配置iptables 安装httpd,开放http访问 /var/tmp/user1下目录 1.安装和用 ...
- CentOS下Supervisor的安装与使用入门
[转载]http://www.51bbo.com/archives/2120 Supervisor是一个进程管理工具,官方的说法 用途就是有一个进程需要每时每刻不断的跑,但是这个进程又有可能由于各种原 ...
- Ubuntu下查看软件版本及安装位置
查看软件版本: XXX --version 或 aptitude show xxx 也可用apt-show-versions (要先安装sudo apt-get install apt-show-ve ...
- CF614A【签到题】
题目链接[http://codeforces.com/problemset/problem/614/A] 题意:输入三个数l.r.k(1 ≤ l ≤ r ≤ 1018, 2 ≤ k ≤ 109),输出 ...
- JZYZOJ1261 字典序最小的lis
http://172.20.6.3/Problem_Show.asp?id=1261 求字典序方法: f[i]表示i位数字的最长上升子序列长度,len为最长上升子序列长度,ans[t]为第t位答案 ...
- 【DP】BZOJ1564- [NOI2009]二叉查找树(!!)
[题目大意] 已知一个treap上每个节点的键值.权值和访问频率.现在可以修改一些节点的权值(可以修改为实数),需要付出k(k为定制)的额外代价.一个treap的总代价=∑(每个节点的访问频率*深度) ...
- finish/onDestroy/System.exit()的区别
Activity.finish():Call this when your activity is done and should be closed. 在你的activity动作完成的时候,或者Ac ...
- Arab Collegiate Programming Contest 2012 J- Math Homework
思路:由于只有1-6这几个数,而这几个数的最小公倍数是60,所以只需要求出60以内有多少满足条件的数即可. 再就是求出对于给定的n,求出60的倍数.然后就是怎样求的问题了. 首先可以写成如下形式: ...
- noip2011初赛提高组 试题详解
转载自:https://blog.csdn.net/Eirlys_North/article/details/52889993 一.单项选择题(共20题,每题1.5分,共计30分,每题有且仅有一个正确 ...