zoukankan      html  css  js  c++  java
  • libevent的使用方法--回显服务器的简单实例

    #include <event.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <string.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <fcntl.h>
    #include <unistd.h>
    
    #define SERVER_PORT 8080
    int debug = 0;
    
    struct client {
      int fd;
      struct bufferevent *buf_ev;
    };
    
    int setnonblock(int fd)
    {
      int flags;
    
      flags = fcntl(fd, F_GETFL);
      flags |= O_NONBLOCK;
      fcntl(fd, F_SETFL, flags);
    }
    
    void buf_read_callback(struct bufferevent *incoming,
                           void *arg)
    {
      struct evbuffer *evreturn;
      char *req;
    
      req = evbuffer_readline(incoming->input);
      if (req == NULL)
        return;
    
      evreturn = evbuffer_new();
      evbuffer_add_printf(evreturn,"You said %s
    ",req);
      bufferevent_write_buffer(incoming,evreturn);
      evbuffer_free(evreturn);
      free(req);
    }
    
    void buf_write_callback(struct bufferevent *bev,
                            void *arg)
    {
    }
    
    void buf_error_callback(struct bufferevent *bev,
                            short what,
                            void *arg)
    {
      struct client *client = (struct client *)arg;
      bufferevent_free(client->buf_ev);
      close(client->fd);
      free(client);
    }
    
    void accept_callback(int fd,
                         short ev,
                         void *arg)
    {
      int client_fd;
      struct sockaddr_in client_addr;
      socklen_t client_len = sizeof(client_addr);
      struct client *client;
    
      client_fd = accept(fd,
                         (struct sockaddr *)&client_addr,
                         &client_len);
      if (client_fd < 0)
        {
          warn("Client: accept() failed");
          return;
        }
    
      setnonblock(client_fd);
    
      client = calloc(1, sizeof(*client));
      if (client == NULL)
        err(1, "malloc failed");
      client->fd = client_fd;
    
      client->buf_ev = bufferevent_new(client_fd,
                                       buf_read_callback,
                                       buf_write_callback,
                                       buf_error_callback,
                                       client);
    
      bufferevent_enable(client->buf_ev, EV_READ);
    }
    
    int main(int argc,
             char **argv)
    {
      int socketlisten;
      struct sockaddr_in addresslisten;
      struct event accept_event;
      int reuse = 1;
    
      event_init();
    
      socketlisten = socket(AF_INET, SOCK_STREAM, 0);
    
      if (socketlisten < 0)
        {
          fprintf(stderr,"Failed to create listen socket");
          return 1;
        }
    
      memset(&addresslisten, 0, sizeof(addresslisten));
    
      addresslisten.sin_family = AF_INET;
      addresslisten.sin_addr.s_addr = INADDR_ANY;
      addresslisten.sin_port = htons(SERVER_PORT);
    
      if (bind(socketlisten,
               (struct sockaddr *)&addresslisten,
               sizeof(addresslisten)) < 0)
        {
          fprintf(stderr,"Failed to bind");
          return 1;
        }
    
      if (listen(socketlisten, 5) < 0)
        {
          fprintf(stderr,"Failed to listen to socket");
          return 1;
        }
    
      setsockopt(socketlisten,
                 SOL_SOCKET,
                 SO_REUSEADDR,
                 &reuse,
                 sizeof(reuse));
    
      setnonblock(socketlisten);
    
      event_set(&accept_event,
                socketlisten,
                EV_READ|EV_PERSIST,
                accept_callback,
                NULL);
    
      event_add(&accept_event,
                NULL);
    
      event_dispatch();
    
      close(socketlisten);
    
      return 0;
    }


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

    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。

    $ telnet localhost 8080
    Trying 127.0.0.1...
    Connected to localhost.
    Escape character is '^]'.
    Hello!
    You said Hello!


    测试的时候可以使用上面的方法!

  • 相关阅读:
    php l练习(写着玩)
    位、字节、字
    ueditor上传图片时目录创建失败的问题解决方法
    tp5插入百度富文本编辑器UEditor
    PHP实现用户异地登录提醒功能的方法
    tp5知识点
    TP5语法
    微擎url
    微擎多图片上传
    微擎函数Iserializer和Iunserializer序列化函数
  • 原文地址:https://www.cnblogs.com/fuhaots2009/p/3483442.html
Copyright © 2011-2022 走看看