Based on some examples on the Internet, we experimented with the development of bufferevent.
The first is the service side:
#include <netinet/inch.h>#include<sys/socket.h>#include<unistd.h>#include<stdio.h>#include<string.h>#include<Event.h>#include<event2/listener.h>#include<event2/bufferevent.h>#include<event2/thread.h>using namespacestd;voidLISTENER_CB (Evconnlistener *Listener, evutil_socket_t FD, sockaddr*sock,intSocklen,void*Arg);voidSOCKET_READ_CB (Bufferevent *bev,void*Arg);voidSOCKET_EVENT_CB (Bufferevent *bev, ShortEventsvoid*Arg);intMainintargcChar**argv) {sockaddr_in sin; memset (&sin,0,sizeof(sockaddr_in)); Sin.sin_family=af_inet; Sin.sin_port= Htons (8899); Event_base*Base=event_base_new (); Evconnlistener*Listener= Evconnlistener_new_bind (Base, LISTENER_CB,Base, Lev_opt_reuseable|Lev_opt_close_on_free,Ten, (sockaddr*) &sin,sizeof(sockaddr_in)); Event_base_dispatch (Base); Evconnlistener_free (listener); Event_base_free (Base);}voidLISTENER_CB (Evconnlistener *Listener, evutil_socket_t FD, sockaddr*sock,intSocklen,void*Arg) {printf ("accept a client%d\n", FD); Event_base*Base= (Event_base *) Arg; Bufferevent*bev = Bufferevent_socket_new (Base, FD, Bev_opt_close_on_free); BUFFEREVENT_SETCB (Bev, SOCKET_READ_CB, NULL, SOCKET_EVENT_CB, NULL); Bufferevent_enable (Bev, Ev_read|ev_persist);}voidSOCKET_READ_CB (Bufferevent *bev,void*Arg) { Charmsg[4096]; size_t Len= Bufferevent_read (Bev, MSG,sizeof(msg)-1); Msg[len]=' /'; printf ("Server Read the data:%s\n", MSG); CharReply[] ="I have read your data."; Bufferevent_write (Bev, reply, strlen (Reply));}voidSOCKET_EVENT_CB (Bufferevent *bev, ShortEventsvoid*Arg) { if(Events &bev_event_eof) {printf ("Connection closed\n"); } Else if(Events &bev_event_error) {printf ("some other error\n"); } bufferevent_free (Bev);}
Compile command:
g++-O lserver lserver.cpp-i/usr/local/include-levent-l/usr/local/lib-wl,-rpath=/usr/local/lib
Then the client:
#include <sys/types.h>#include<sys/socket.h>#include<netinet/inch.h>#include<arpa/inet.h>#include<errno.h>#include<unistd.h>#include<stdio.h>#include<string.h>#include<stdlib.h>#include<Event.h>#include<event2/bufferevent.h>#include<event2/buffer.h>#include<event2/util.h>intTcp_connect_server (Const Char*SERVER_IP,intport);voidCMD_MSG_CB (intFd ShortEventsvoid*Arg);voidSERVER_MSG_CB (Bufferevent *bev,void*Arg);voidEVENT_CB (Bufferevent *bev, Short Event,void*Arg);intMainintargcChar**argv) { if(ARGC <3) {printf ("Please input IP and port\n"); return 1; } event_base*Base=event_base_new (); Bufferevent*bev = Bufferevent_socket_new (Base, -1, Bev_opt_close_on_free); Event*ev_cmd = Event_new (Base, Stdin_fileno, Ev_read|ev_persist, CMD_MSG_CB, (void*) Bev); Event_add (Ev_cmd, NULL); Sockaddr_in server_addr; memset (&SERVER_ADDR,0,sizeof(SERVER_ADDR)); Server_addr.sin_family=af_inet; Server_addr.sin_port= Htons (Atoi (argv[2])); Inet_aton (argv[1], &server_addr.sin_addr); Bufferevent_socket_connect (Bev, (Sockaddr*) &server_addr,sizeof(SERVER_ADDR)); BUFFEREVENT_SETCB (Bev, SERVER_MSG_CB, NULL, EVENT_CB, (void*) ev_cmd); Bufferevent_enable (Bev, Ev_read|ev_persist); Event_base_dispatch (Base); printf ("finished\n"); return 0;}voidCMD_MSG_CB (intFd ShortEventsvoid*Arg) { Charmsg[1024x768]; intret = read (FD, MSG,sizeof(msg)); if(Ret <0) {perror ("Read fail.\n"); Exit (1); } bufferevent*bev = (Bufferevent *) Arg; Bufferevent_write (Bev, MSG, ret);}voidSERVER_MSG_CB (Bufferevent *bev,void*Arg) { Charmsg[1024x768]; size_t Len= Bufferevent_read (Bev, MSG,sizeof(msg)-1); Msg[len]=' /'; printf ("Recv%s from server.\n", msg);}voidEVENT_CB (Bufferevent *bev, Short Event,void*Arg) { if(Event&bev_event_eof) {printf ("Connection closed.\n"); } Else if(Event&bev_event_error) {printf ("Some Other error.\n"); } Else if(Event&bev_event_connected) {printf ("Client has successfully cliented.\n"); return; } bufferevent_free (BEV); //Free event_cmd//need struct as event is defined as parameter struct Event*ev = (struct Event*) Arg; Event_free (EV);}
Compile command:
g++-O lclient lclient.cpp-i/usr/local/include-levent-l/usr/local/lib-wl,-rpath=/usr/local/lib
To run the server command:
./lserver
To run the client command:
127.0. 0.1 8899
The output from both sides after multiple interactions is:
[server]$./lserver accept a client 7 server read the Data:aaaserver read the data:bbbserver read the Data:cccserver rea D The Data:dddserver read the data:eeeee
127.0. 0.1 8899 from andfrom server.
If you close the client first (CTRL-C, which is SIGINT), the server will print a prompt, but you can still accept other requests.
[server]$./77Server Read the DATA:TTT
If you first close the server side (Ctrl-c, which is SIGINT), the client also shuts down:
127.0. 0.1 8899 from server. Connection closed. Finished
This is because the associated event on the client, including the socket's event (closed by Bufferevent_free), and the Cmd event (which is closed by Event_free), have been closed. Then the whole Event_base_dispatch cycle returns.
Development of Libevent server and client using Bufferevent