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\n",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!


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

 

 

你可能感兴趣的:(libevent)