Libevent in the project

Source: Internet
Author: User
The single-threaded libevent mode Project is a multi-threaded version. First, I understand the single-threaded version. // Client1. call NGP: Init () bool NGP: Init (ngpcontext context) {_ context = context; // _ tcplink = newsp (tcplink ); _ tcplink = newsp (tcplinkex); _ tcplink-> Init (this); Return true;} 2. initialize libeventbool libevtserver: Init (I _netserverevent * event, int start, int size) {m_ids = new channelidgenerator (); m_ids-> Init (START, size ); m_allchannels.resize (m_ids-> getsize (); m_event = event; // use Windows mode thread and lock int hR = Evthread_use_windows_threads (); // currently, there are two threads. One master thread and one dispatch thread. // one thread has only one event_base, which corresponds to a struct event_base struct and the corresponding event manager, this event manager manages the event m_base = event_base_new () bound to this event_base; // creates event_base if (! M_base) {fprintf (stderr, "cocould not initialize libevent! \ N "); Return false;} return true;} 3. listening. Why does the client listen to bool libevtserver: Listen (int * port) {struct sockaddr_in sin; memset (& sin, 0, sizeof (SIN); sin. sin_family = af_inet; If (-1 = * port) sin. sin_port = htons (10000); else sin. sin_port = htons (* port); // call evconnlistener_new_bind if the libevent is allocated and bound to the socket. This is equivalent to the original socket (), BIND (), and listen (), then a connection will call listener_cb // Where evutil_make_socket_nonblocking is called and the socket is set to non-blocking, Bind binding, evconnlistener_new creates the listener, and then returns the listener // connection listener using event_base to know when a TCP connection is established on the listener socket, when a connection is established, the callback function m_listener = evconnlistener_new_bind (m_base,: listener_cb, (void *) This, // evconnlistener_new_bind provides a method to listen to and accept TCP, this requires libevent to allocate and bind socket lev_opt_reuseable | lev_opt_close_on_free,-1, (struct sockaddr *) & sin, sizeof (SIN); If (! M_listener) {return false;} If (-1 = * port) * Port = ntohs (SIN. sin_port); If (! M_listener) {fprintf (stderr, "cocould not create a listener! \ N "); Return false;} m_spthread.reset (new STD: thread ([this] {// setthreadpriority (getcurrentthread (), thread_priority_highest); // event_base_loop (m_base, evloop_once); // The events bound to the epoll/kqueue system call are automatically called when an event occurs, but these events need to be bound to event_base event_base_dispatch (m_base ); // start the event_base loop. event_base_dispatch is a while loop. The project directly opens a thread to obtain the IF (wsaenotsock = wsagetlasterror () {plug :: plugmessagebox (L "the socket is invalid! ");} Plug: plugmessagebox (L" libevent dispatching thread exited! ") ;})); Return true;} 4. client Connection bool libevtserver: connet_to (int ip, int port) {// create a socket-based bufferevent, and host it to event_base // buffevent. From the word, we can see that it is the buffer on the event, that is, there are input and output buffers on the read/write events. // It is the file descriptor, determine which file is written and written. You can regard the socket as the file descriptor, but cannot set it to pipe (2). For security reasons, you can set it to-1, then set it with bufferevent_setfd or bufferevent_socket_connect (). auto Bev = bufferevent_socket_new (m_base,-1, bev_opt_close_on_free | bev_opt_thre Adsafe); // create a bufferevent, associate with sockfd, and host it to event_base if (! BEV) {STD: cout <"bufferevent_socket_new error! "<STD: Endl; return false;} struct sockaddr_in sin; sin. sin_family = af_inet; sin. sin_addr.s_addr = ntohl (IP); sin. sin_port = htons (port); // connection // If the bufferevent does not already have a socket set, we allocate a new socket here and make it nonblocking before we begin. int hR = bufferevent_socket_connect (BEV, (struct sockaddr *) & sin, sizeof (SIN); If (0! = HR) return false; STD: lock_guard <STD: mutex> lock (m_offline_ctx); // apply to release the channel ID and lock auto C2 = createchannel (BEV ); // set the callback bufferevent_setcb (BEV, conn_readcb, conn_writecb, conn_eventcb, C2) on the bufferevent; // set the read/write event // start bufferevent bufferevent_enable (BEV, ev_read | ev_write ); // start the read/write event and put the read/write event into the listening queue poll and return true;} // --------------------------------- libevent ready for the client --------------------- ---- // Server/* member function */bool libevtserver: Init (I _netserverevent * event, int start, int size) {m_ids = new channelidgenerator (); m_ids-> Init (START, size); m_allchannels.resize (m_ids-> getsize (); m_event = event; // event supports multi-thread initialization function int hR = evthread_use_windows_threads (); m_base = event_base_new (); If (! M_base) {fprintf (stderr, "cocould not initialize libevent! \ N "); Return false;} return true;} // listener port.-1 indicates applying to the system for any available port bool libevtserver: Listen (int * port) {struct sockaddr_in sin; memset (& sin, 0, sizeof (SIN); sin. sin_family = af_inet; If (-1 = * port) sin. sin_port = htons (10000); else sin. sin_port = htons (* port); m_listener = evconnlistener_new_bind (m_base,: listener_cb, (void *) This, lev_opt_reuseable | struct,-1, (struct sockaddr *) & sin, siz EOF (SIN); If (! M_listener) {return false;} If (-1 = * port) * Port = ntohs (SIN. sin_port); If (! M_listener) {fprintf (stderr, "cocould not create a listener! \ N "); Return false;} m_spthread.reset (new STD: thread ([this] {// setthreadpriority (getcurrentthread (), thread_priority_highest); // event_base_loop (m_base, evloop_once); event_base_dispatch (m_base); If (wsaenotsock = wsagetlasterror () {plug: plugmessagebox (L "the socket is invalid! ");} Plug: plugmessagebox (L" libevent dispatching thread exited! ");}); Return true;} // then, in the callback function in the listener,/* New Connection event processing */typedef void (* evconnlistener_cb) (struct evconnlistener *, evutil_socket_t, struct sockaddr *, int socklen, void *); // This is the callback prototype static void listener_cb (struct evconnlistener * listener, evutil_socket_t FD, struct sockaddr * Sa, int socklen, void * user_data) {auto SER = (libevtserver *) user_data; ser-> listener_cb (listener, FD, SA, socklen, user_data );} Void libevtserver: listener_cb (struct evconnlistener * listener, evutil_socket_t FD, struct sockaddr * Sa, int socklen, void * user_data) {// obtain event_base auto base = evconnlistener_get_base (listener) related to listener; // create a socket bufferevent auto Bev = bufferevent_socket_new (base, FD, bev_opt_threadsafe ); // bev_opt_close_on_free | if (! BEV) {fprintf (stderr, "error constructing bufferevent! "); Event_base_loopbreak (base); return;} auto C2 = createchannel (BEV); // set the callback bufferevent_setcb (BEV, conn_readcb, null, conn_eventcb, C2 ); // start bufferevent bufferevent_enable (BEV, ev_read | ev_write);} // the server process is similar to that of the client. // The libevent process is based on the socket bufferevent of event_base, in event_base_dispath, I do not know whether to use select or iocp. Then I find that the socket status changes to readable, writable, or // error will call the corresponding registration time, the established socket is not blocked. I still don't know when to call this read/write callback. What is the difference between it and the read/write buffer.

 

Libevent in the project

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.