[原]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客户端例子的更多相关文章

  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. vars 变量预解析

    JavaScript中,你可以在函数的任何位置声明多个var语句,并且它们就好像是在函数顶部声明一样发挥作用,这种行为称为 hoisting(悬置/置顶解析/预解析).当你使用了一个变量,然后不久在函 ...

  2. ApplicationContext中getBean详解

    在org.springframework.context包中有一个接口叫 applicationContext applicationContext中有一个getBean方法,此方法继承之BeanFa ...

  3. Java多线程编程——wait()和notify()、notifyAll()

    1.源码 wait() notify() notifyAll()都是Object类中方法.源码如下所示: public final native void notify(); public final ...

  4. Linux-数据库1

    数据库介绍 数据库(database,DB)是指长期存储在计算机内的,有组织,可共享的数据的集合.数据库中的数据按一定的数学模型组织.描述和存储,具有较小的冗余,较高的数据独立性和易扩展性,并可为各种 ...

  5. hdu 2433 Travel(还不会)

    Problem Description       One day, Tom traveled to a country named BGM. BGM is a small country, but ...

  6. 什么是P问题、NP问题和NPC问题

    为了迎接我的期末考试,认真的看了一下关于NP完全性理论这一章,奈何课本上说的我怎么都看不懂,所以找了个博客认真研究了一下,同样贴出来分享给大家,大牛就是大牛,把问题说的很明白,看完后受益匪浅.其中有一 ...

  7. BZOJ1002輪狀病毒 暴搜 + 找規律 + 高精度

    @[暴搜, 找規律, 高精度] Description 轮状病毒有很多变种,所有轮状病毒的变种都是从一个轮状基产生的.一个\(n\)轮状基由圆环上\(n\)个不同的基原子和圆心处一个核原子构成的,2个 ...

  8. poj 2828 buy Tickets 用线段树模拟带插入的队列

    Buy Tickets Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=2 ...

  9. 【弱省胡策】Round #0 Flower Dance DP

    Flower Dance Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://162.105.80.126/contest/%E3%80%90%E ...

  10. python string和dict转换

    字典(dict)转为字符串(string) 我们可以比较容易的将字典(dict)类型转为字符串(string)类型. 通过遍历dict中的所有元素就可以实现字典到字符串的转换: for key, va ...