libevent实现echoclient

基于libevent实现了一个简单的echoclient。之前在网上看到的都是echoserver。这里演示一下使用libevent进行客户端编程的基本步骤。

先看代码:

[cpp]  view plain  copy
  1. #include "stdafx.h"  
  2. #include "event2/event.h"  
  3. #include "event2/util.h"  
  4.   
  5. #define ECHO_PORT   8888  
  6. #define ECHO_SERVER "127.0.0.1"  
  7.   
  8. struct echo_context{  
  9.     struct event_base *base;  
  10.     struct event *event_write;  
  11.     struct event *event_read;  
  12.     const char * echo_contents;  
  13.     int echo_contents_len;  
  14.     int recved;  
  15. };  
  16.   
  17. void write_cb(evutil_socket_t sock, short flags, void * args)  
  18. {  
  19.     struct echo_context *ec = (struct echo_context *)args;   
  20.   
  21.     int ret = send(sock, ec->echo_contents, ec->echo_contents_len, 0);  
  22.     printf("connected, write to echo server: %d\n", ret);  
  23.     event_add(ec->event_read, 0);  
  24. }  
  25.   
  26. void read_cb(evutil_socket_t sock, short flags, void * args)  
  27. {  
  28.     struct echo_context *ec = (struct echo_context *)args;   
  29.     char buf[128];  
  30.     int ret = recv(sock, buf, 128, 0);  
  31.       
  32.     printf("read_cb, read %d bytes\n", ret);  
  33.     if(ret > 0)  
  34.     {  
  35.         ec->recved += ret;  
  36.         buf[ret] = 0;  
  37.         printf("recv:%s\n", buf);  
  38.     }  
  39.     else if(ret == 0)  
  40.     {  
  41.         printf("read_cb connection closed\n");  
  42.         event_base_loopexit(ec->base, NULL);  
  43.         return;  
  44.     }  
  45.     if(ec->recved < ec->echo_contents_len)  
  46.     {  
  47.         event_add(ec->event_read, 0);  
  48.     }  
  49. }  
  50.   
  51. static evutil_socket_t make_tcp_socket()  
  52. {  
  53.     int on = 1;  
  54.     evutil_socket_t sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);  
  55.   
  56.     evutil_make_socket_nonblocking(sock);  
  57. #ifdef WIN32  
  58.     setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (const char *)&on, sizeof(on));  
  59. #else  
  60.     setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (void *)&on, sizeof(on));  
  61. #endif  
  62.   
  63.     return sock;  
  64. }  
  65.   
  66. static void echo_client(struct event_base *base)  
  67. {  
  68.     evutil_socket_t sock = make_tcp_socket();  
  69.     struct sockaddr_in serverAddr;  
  70.     struct event * ev_write = 0;  
  71.     struct event * ev_read = 0;  
  72.     struct timeval tv={10, 0};  
  73.     struct echo_context *ec = (struct echo_context*)calloc(1, sizeof(struct echo_context));  
  74.       
  75.     serverAddr.sin_family = AF_INET;  
  76.     serverAddr.sin_port = htons(ECHO_PORT);  
  77. #ifdef WIN32  
  78.     serverAddr.sin_addr.S_un.S_addr = inet_addr(ECHO_SERVER);  
  79. #else  
  80.     serverAddr.sin_addr.s_addr = inet_addr(ECHO_SERVER);  
  81. #endif  
  82.     memset(serverAddr.sin_zero, 0x00, 8);  
  83.   
  84.     connect(sock, (struct sockaddr*)&serverAddr, sizeof(serverAddr));  
  85.   
  86.     ev_write = event_new(base, sock, EV_WRITE, write_cb, (void*)ec);  
  87.     ev_read = event_new(base, sock, EV_READ , read_cb, (void*)ec);  
  88.   
  89.     ec->event_write = ev_write;  
  90.     ec->event_read = ev_read;  
  91.     ec->base = base;  
  92.     ec->echo_contents = strdup("echo client tneilc ohce\n");  
  93.     ec->echo_contents_len = strlen(ec->echo_contents);  
  94.     ec->recved = 0;  
  95.   
  96.     event_add(ev_write, &tv);  
  97. }  
  98.   
  99. int _tmain(int argc, _TCHAR* argv[])  
  100. {  
  101.     struct event_base * base = 0;  
  102. #ifdef WIN32  
  103.     WORD wVersionRequested;  
  104.     WSADATA wsaData;  
  105.   
  106.     wVersionRequested = MAKEWORD(2, 2);  
  107.   
  108.     (void) WSAStartup(wVersionRequested, &wsaData);  
  109. #endif  
  110.   
  111.     base = event_base_new();  
  112.     echo_client(base);  
  113.     event_base_dispatch(base);  
  114.     event_base_free(base);  
  115.   
  116.     return 0;  
  117. }  

代码是在windows上实现的。

使用libevent进行客户端编程的基本步骤,在《libevent实现http client》中已经提过,基本如下:

  1. 初始化event_base(后续要运行事件循环)
  2. 创建socket,设置为异步,连接server
  3. 创建写读写事件,先将写事件加入事件循环
  4. 在写事件回调中向server端发送请求并将读事件加入事件循环
  5. 在读事件回调中处理数据,并根据数据是否读取完毕决定是否继续添加读事件
结合本文的示例代码,通过event_base_new()创建event_base,在初始化客户端socket(echo_client)之后,调用event_base_dispatch运行事件循环。

echo_client函数初始化了socket,设置为非阻塞模式,调用connect连接到echoserver,然后添加一个写事件到事件循环中。当连接成功后,会触发写事件。这里将write_cb作为写事件的回调,在调用event_new()时传入。

write_cb()写入一个字符串,然后添加一个读事件,在读事件中读取echoserver的回应。

基本的过程就是这样子了。这是个简单的例子,更复杂的例子,基本流程也是一样的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值