Implementation of Simple Libevent server _ server in Windows other

Source: Internet
Author: User
Tags assert manual posix sin socket socket error strlen htons

Recently learned libevent because of its use of the Windows system, unfortunately, there are few programs that can be referenced under vs. After referring to a number of blog posts. I groped myself to write a simple libevent server program. And found a simple client program on the Internet to test the success of the code. Make a note here today.

Libevent is really a very good thing, but also continue to learn, the follow-up will also be implemented under Windows Libevent multithreading use. Today, first of all to put up their own things to put up, only for learning reference. Compile on the vs2015.

By default it is single-threaded (can be configured as multiple threads, if necessary), each thread has and only one event base, corresponding to a struct event_base structure (and the event manager attached to it), used to schedule a series of events hosted on it, The process management analogy with the operating system, of course, is simpler. When an event occurs, Event_base will call the function bound on the event (not immediately) at the appropriate time (passing in some predefined parameters, and a parameter specified at bind) until the function is finished and then returns schedule other events.

 Create a event_base
struct event_base *base = event_base_new ();
ASSERT (base!= NULL); 

There is a loop inside the event_base that loops over system calls such as epoll/kqueue until one/some events occur, and then the events are processed. Of course, these events are bound to be on this event_base. Each event corresponds to a struct event, which can be monitored for an FD or POSIX semaphore, and so on (here's the FD, and the other manual). struct event uses event_new to create and bind, using Event_add to enable:

 Create and bind an event
struct event *listen_event;
Parameters: Event_base, monitor FD, event type and attribute, binding callback function,
 
listen_event = Event_new for callback function (base, listener, Ev_read | Ev_persist, Callback_func, (void*) base);
Parameters: Event, timeout (struct timeval * type, NULL indicates no timeout setting)
event_add (listen_event, NULL);

Note:The events and attributes supported by Libevent include (using Bitfield implementations, so they can be merged with |)

(a) Ev_timeout: timeout
(b) Ev_read: As long as there is data in the network buffer, the callback function will be triggered
(c) Ev_write: The callback function is triggered whenever the data that is plugged into the network is written out
(d) ev_signal:posix signal volume, refer to Manual bar
(e) Ev_persist: If this property is not specified, the event is deleted when the callback function is triggered
(f) Ev_et:edge-trigger edge trigger, reference Epoll_et
You then need to start the event_base loop so that you can start processing the events that occurred. Loop Start Event Base Dispatch, the loop continues until there are no more events to focus on, or the event_loopbreak ()/event_loopexit () function is encountered.
//Start Event loop
Event_base_dispatch (base);

Next, focus on the callback function that is bound to the event Callback_func: It's a socket FD, an event type and attribute Bit_field, and the last argument passed to the event_new (go over the top lines and review the event _base to pass in, in fact more is the allocation of a structure, the relevant data are put in, and then dropped to event_new, here can be achieved. Its prototype is:
typedef void (*EVENT_CALLBACK_FN) (evutil_socket_t sockfd, short event_type, void *arg)

For a server, the above process is probably the same combination:
1. Listener = socket (), bind (), listen (), set nonblocking (the FCNTL setting can be used in the POSIX system, Windows does not need to be set,
In fact Libevent provides a uniform packaging evutil_make_socket_nonblocking)
2. Create a Event_base
3. Create an event, host the socket to Event_base, specify the type of event to listen to, and bind the corresponding callback function (and the parameters that need to be given)
。 For listener sockets, you only need to listen for Ev_read | Ev_persist
4. Enable this event
5. Enter the event cycle
-------------- -
6. (asynchronous) When a client initiates a request, the callback function is invoked for processing.
/* Next attention is given to the callback function bound to the event Callback_func: It is passed to a socket FD, an event type and attribute Bit_field, and the last argument passed to the event_new (go over the lines above to review, Event_base to pass in, in fact more is to allocate a structure, the relevant data are put in, and then dropped to event_new, here can be achieved. */

server-side code: Server.cpp

  #include <WinSock2.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #inclu
  De <errno.h> #include <event2/event.h> #include <event2/bufferevent.h> #include <iostream> #include <cassert> #pragma comment (lib, "Ws2_32.lib") #include <ws2tcpip.h> #define LISTEN_PORT 9999 #de
 Fine Liaten_backlog using namespace std; /********************************************************************************* * Function Declaration ************ ///accept back off function void Do_accept_cb (Evutil_
 socket_t Listener, short event, void *arg);
 Read callback function void Read_cb (struct bufferevent *bev, void *arg);
 Error callback function void Error_cb (struct bufferevent *bev, short event, void *arg);
 Write callback function void Write_cb (struct bufferevent *bev, void *arg);                /*********************************************************************************
 *   function body **********************************************************************************///accept return function void Do_ ACCEPT_CB (evutil_socket_t Listener, short event, void *arg) {//incoming event_base pointer struct event_base = (*base E
   vent_base*) Arg;
   Socket descriptor evutil_socket_t FD;
   Statement address struct sockaddr_in sin;
   Address length declaration socklen_t slen = sizeof (SIN);
   Receive Client FD = Accept (listener, (struct sockaddr *) &sin, &slen);
     if (FD < 0) {perror ("error accept");
   Return
   printf ("ACCEPT:FD =%u\n", FD);
   Register a bufferevent_socket_new event struct bufferevent *bev = bufferevent_socket_new (base, FD, Bev_opt_close_on_free);
   Set Back off function BUFFEREVENT_SETCB (Bev, READ_CB, NULL, ERROR_CB, ARG); Set the properties of the event bufferevent_enable (Bev, Ev_read | Ev_write |
 Ev_persist);
   }////read callback function void Read_cb (struct bufferevent *bev, void *arg) {#define Max_line 256 char Line[max_line + 1];
   int n; Socket FD Bev found by passing in the parameter evutil_socket_T fd = BUFFEREVENT_GETFD (BEV);
     while (n = bufferevent_read (Bev, Line, Max_line)) {line[n] = ';
     printf ("fd=%u, read line:%s\n", FD, line);
   Returns the obtained data to the client Bufferevent_write (Bev, line, N); }////error callback function void Error_cb (struct bufferevent *bev, short event, void *arg) {//The socket FD is found by passing in the parameter Bev Evutil
   _socket_t FD = BUFFEREVENT_GETFD (BEV);
   cout << "fd =" << fd << Endl;  if (event & Bev_event_timeout) {printf ("Timed out\n");//if bufferevent_set_timeouts () called} else if
   (Event & Bev_event_eof)
   {printf ("Connection closed\n");
   else if (event & Bev_event_error) {printf ("some other error\n");
 } bufferevent_free (BEV);
   }////write callback function void Write_cb (struct bufferevent *bev, void *arg) {char str[50];
   By passing in the parameter Bev find the socket FD evutil_socket_t FD = BUFFEREVENT_GETFD (BEV);
   CIN >> str; printf ("Enter data!")
   ");
   scanf_s ("%d", &str); BuffereveNt_write (Bev, &AMP;STR, sizeof (str));
   int main () {int ret;
   EVUTIL_SOCKET_T Listener;
   Wsadata Ws;
   Init Windows Socket if (WSAStartup (Makeword (2, 2), &ws)!= 0) {return-1;
   } listener = socket (af_inet, sock_stream, 0);
   ASSERT (Listener > 0);
   Evutil_make_listen_socket_reuseable (listener);
   struct sockaddr_in sin;
   sin.sin_family = af_inet;
   sin.sin_addr.s_addr = 0;
   Sin.sin_port = htons (Listen_port);
     if (Bind (listener, (struct sockaddr *) &sin, sizeof (SIN)) < 0) {perror ("bind");
   return 1;
     } if (Listen (listener, 1000) < 0) {perror ("listen");
   return 1;
   printf ("listening...\n");
   Evutil_make_socket_nonblocking (listener);
   struct Event_base *base = event_base_new ();
   ASSERT (base!= NULL);
   struct event *listen_event; Listen_event = Event_new (base, Listener, Ev_read |
   Ev_persist, DO_ACCEPT_CB, (void*) base);
   Event_add (Listen_event, NULL);
   Event_base_dispatch (base); PrinTF ("the End.");
 return 0; }

Client code: Client.cpp

/******* client program client.c ************/#define _WINSOCK_DEPRECATED_NO_WARNINGS #define _crt_secure_no_warnings #include <stdlib.h> #include <stdio.h> #include <errno.h> #include <string.h> #include <winsock2.h > #include <ws2tcpip.h> #include <iostream> #pragma comment (lib, "Ws2_32.lib") int main (int argc, char *a
   Rgv[]) {wsadata Ws;
   Init Windows Socket if (WSAStartup (Makeword (2, 2), &ws)!= 0) {return 0;
   int sockfd;
   Char buffer[1024];
   struct sockaddr_in server_addr;
   struct Hostent *host;
 
   int PortNumber, nbytes;
     if (host = gethostbyname ("127.0.0.1")) = = NULL) {fprintf (stderr, GetHostName error\n);
   Exit (1);
     } if ((PortNumber = atoi ("9999")) <0) {fprintf (stderr, usage:%s hostname portnumber\a\n, argv[0]);
   Exit (1);  /* Client program started to establish SOCKFD descriptor/if (SOCKFD = socket (af_inet, sock_stream, 0)) = = 1) {fprintf (stderr, "socket Error:%s\a\ n ", Strerror (errno));
   Exit (1);
   /* Client program to populate service-side information * * memset (&server_addr,0, sizeof (SERVER_ADDR));
   server_addr.sin_family = af_inet;
   Server_addr.sin_port = htons (portnumber);
 
   server_addr.sin_addr = * (struct in_addr *) host->h_addr);
     /* Client initiates connection request/if (Connect (SOCKFD, (struct sockaddr *) (&AMP;SERVER_ADDR), sizeof (struct sockaddr)) = = 1) {
     fprintf (stderr, "Connect error:%s\a\n", Strerror (errno));
   Exit (1); } while (true) {char message[] = "Hello server ...".
     \ n "; 
     Bufferevent_write (Buf_ev,message,strlen (message));
       if ( -1 = (:: Send (SOCKFD, message, strlen (message), 0)) {printf ("The net has a error occured ...");
     Break } if ((Nbytes = recv (sockfd, buffer, 1024,0)) = = 1) {fprintf (stderr, "read error:%s\n", Strerror (errno
       ));
     Exit (1);
     } Buffer[nbytes] = ';
     printf ("I have received:%s\n", buffer);
 
  memset (buffer, 0, 1024);   Sleep (2);
   }/* End communication/closesocket (SOCKFD);
 
   Exit (0);
 return 0;
 }

The above is the entire content of this article, I hope to help you learn, but also hope that we support the cloud habitat community.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.