libevent的使用方法--回显服务器的简单实例

来源:互联网 发布:java源码是什么 编辑:程序博客网 时间:2024/06/05 02:31
[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. #include <event.h>  
  2. #include <sys/types.h>  
  3. #include <sys/socket.h>  
  4. #include <netinet/in.h>  
  5. #include <arpa/inet.h>  
  6. #include <string.h>  
  7. #include <stdlib.h>  
  8. #include <stdio.h>  
  9. #include <fcntl.h>  
  10. #include <unistd.h>  
  11.   
  12. #define SERVER_PORT 8080  
  13. int debug = 0;  
  14.   
  15. struct client {  
  16.   int fd;  
  17.   struct bufferevent *buf_ev;  
  18. };  
  19.   
  20. int setnonblock(int fd)  
  21. {  
  22.   int flags;  
  23.   
  24.   flags = fcntl(fd, F_GETFL);  
  25.   flags |= O_NONBLOCK;  
  26.   fcntl(fd, F_SETFL, flags);  
  27. }  
  28.   
  29. void buf_read_callback(struct bufferevent *incoming,  
  30.                        void *arg)  
  31. {  
  32.   struct evbuffer *evreturn;  
  33.   char *req;  
  34.   
  35.   req = evbuffer_readline(incoming->input);  
  36.   if (req == NULL)  
  37.     return;  
  38.   
  39.   evreturn = evbuffer_new();  
  40.   evbuffer_add_printf(evreturn,"You said %s\n",req);  
  41.   bufferevent_write_buffer(incoming,evreturn);  
  42.   evbuffer_free(evreturn);  
  43.   free(req);  
  44. }  
  45.   
  46. void buf_write_callback(struct bufferevent *bev,  
  47.                         void *arg)  
  48. {  
  49. }  
  50.   
  51. void buf_error_callback(struct bufferevent *bev,  
  52.                         short what,  
  53.                         void *arg)  
  54. {  
  55.   struct client *client = (struct client *)arg;  
  56.   bufferevent_free(client->buf_ev);  
  57.   close(client->fd);  
  58.   free(client);  
  59. }  
  60.   
  61. void accept_callback(int fd,  
  62.                      short ev,  
  63.                      void *arg)  
  64. {  
  65.   int client_fd;  
  66.   struct sockaddr_in client_addr;  
  67.   socklen_t client_len = sizeof(client_addr);  
  68.   struct client *client;  
  69.   
  70.   client_fd = accept(fd,  
  71.                      (struct sockaddr *)&client_addr,  
  72.                      &client_len);  
  73.   if (client_fd < 0)  
  74.     {  
  75.       warn("Client: accept() failed");  
  76.       return;  
  77.     }  
  78.   
  79.   setnonblock(client_fd);  
  80.   
  81.   client = calloc(1, sizeof(*client));  
  82.   if (client == NULL)  
  83.     err(1, "malloc failed");  
  84.   client->fd = client_fd;  
  85.   
  86.   client->buf_ev = bufferevent_new(client_fd,  
  87.                                    buf_read_callback,  
  88.                                    buf_write_callback,  
  89.                                    buf_error_callback,  
  90.                                    client);  
  91.   
  92.   bufferevent_enable(client->buf_ev, EV_READ);  
  93. }  
  94.   
  95. int main(int argc,  
  96.          char **argv)  
  97. {  
  98.   int socketlisten;  
  99.   struct sockaddr_in addresslisten;  
  100.   struct event accept_event;  
  101.   int reuse = 1;  
  102.   
  103.   event_init();  
  104.   
  105.   socketlisten = socket(AF_INET, SOCK_STREAM, 0);  
  106.   
  107.   if (socketlisten < 0)  
  108.     {  
  109.       fprintf(stderr,"Failed to create listen socket");  
  110.       return 1;  
  111.     }  
  112.   
  113.   memset(&addresslisten, 0, sizeof(addresslisten));  
  114.   
  115.   addresslisten.sin_family = AF_INET;  
  116.   addresslisten.sin_addr.s_addr = INADDR_ANY;  
  117.   addresslisten.sin_port = htons(SERVER_PORT);  
  118.   
  119.   if (bind(socketlisten,  
  120.            (struct sockaddr *)&addresslisten,  
  121.            sizeof(addresslisten)) < 0)  
  122.     {  
  123.       fprintf(stderr,"Failed to bind");  
  124.       return 1;  
  125.     }  
  126.   
  127.   if (listen(socketlisten, 5) < 0)  
  128.     {  
  129.       fprintf(stderr,"Failed to listen to socket");  
  130.       return 1;  
  131.     }  
  132.   
  133.   setsockopt(socketlisten,  
  134.              SOL_SOCKET,  
  135.              SO_REUSEADDR,  
  136.              &reuse,  
  137.              sizeof(reuse));  
  138.   
  139.   setnonblock(socketlisten);  
  140.   
  141.   event_set(&accept_event,  
  142.             socketlisten,  
  143.             EV_READ|EV_PERSIST,  
  144.             accept_callback,  
  145.             NULL);  
  146.   
  147.   event_add(&accept_event,  
  148.             NULL);  
  149.   
  150.   event_dispatch();  
  151.   
  152.   close(socketlisten);  
  153.   
  154.   return 0;  
  155. }  

下面讨论各个函数及其操作:

1、main():主函数创建用来监听连接的套接字,然后创建 accept() 的回调函数以便通过事件处理函数处理每个连接。

2、accept_callback():当接受连接时,事件系统调用此函数。此函数接受到客户端的连接;添加客户端套接字信息和一个 bufferevent 结构;在事件结构中为客户端套接字上的读/写/错误事件添加回调函数;作为参数传递客户端结构(和嵌入的 eventbuffer 和客户端套接字)。每当对应的客户端套接字包含读、写或错误操作时,调用对应的回调函数。

3、buf_read_callback():当客户端套接字有要读的数据时调用它。作为回显服务,此函数把 "you said..." 写回客户端。套接字仍然打开,可以接受新请求。

4、buf_write_callback():当有要写的数据时调用它。在这个简单的服务中,不需要此函数,所以定义是空的。

5、buf_error_callback():当出现错误时调用它。这包括客户端中断连接。在出现错误的所有场景中,关闭客户端套接字,从事件列表中删除客户端套接字的事件条目,释放客户端结构的内存。

5、setnonblock():设置网络套接字以开放 I/O。

当客户端连接时,在事件队列中添加新事件以处理客户端连接;当客户端中断连接时删除事件。在幕后,libevent 处理网络套接字,识别需要服务的客户端,分别调用对应的函数。为了构建这个应用程序,需要编译 C 源代码并添加 libevent 库:$ gcc -o basic basic.c -levent。

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. $ telnet localhost 8080  
  2. Trying 127.0.0.1...  
  3. Connected to localhost.  
  4. Escape character is '^]'.  
  5. Hello!  
  6. You said Hello!  

测试的时候可以使用上面的方法!
0 0
原创粉丝点击