LibEvent中文帮助文档--第18章【LibEvent编程示例】

时间:2021-09-12 00:17:16


LibEvent中文帮助文档--第18章【LibEvent编程示例】


   返回主目录


Libevent


快速可移植非阻塞式网络编程

 

 

修订历史

版本

日期

作者

备注

V1.0

2016-11-15

周勇

Libevent编程中文帮助文档

 

文档是2009-2012年由Nick-Mathewson基于Attribution-Noncommercial-Share Alike许可协议3.0创建,未来版本将会使用约束性更低的许可来创建.

此外,本文档的源代码示例也是基于BSD"3条款""修改"条款.详情请参考BSD文件全部条款.本文档最新下载地址:

英文:http://libevent.org/

中文:http://blog.csdn.net/zhouyongku/article/details/53431750

请下载并运行"gitclonegit://github.com/nmathewson/libevent- book.git"获取本文档描述的最新版本源码.




<<上一章>>


18.1Event客户端服务器示例

18.1.1客户端

client.c

/*Author:ZhouYong
http://blog.csdn.net/zhouyongku
Date:2016-11-29*/

#include<stdio.h>
#include<stdlib.h>
#include <unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<event2/event.h>

#define MAX_READ_MSG_LEN4096

const char * g_szServerIP = "127.0.0.1";
constshortg_nConnectPort = 15623;

//Wait For socket can read,then call the callback fun.
void OnClientRead(int fd,short narg,void *pParam );


int main()
{


/*------------------------ConnectToServer------------------------*/
int fd = socket(PF_INET,SOCK_STREAM,0);
if( fd<0 )
{
printf("Client Create Socket Error!\n");
return -1;
}

sockaddr_in addr;
inet_aton(g_szServerIP,&addr.sin_addr);
addr.sin_port = htons(g_nConnectPort);
addr.sin_family = PF_INET;

if( connect(fd,(sockaddr*)&addr,sizeof(addr)) <0 )
{
close(fd);
printf("Client Connect To Server ip=%s port=%d failed!!\n",g_szServerIP,g_nConnectPort);
return -1;
}

printf("Client Connect To Server ip=%s port=%d success!\n",g_szServerIP,g_nConnectPort);

sleep(1);
/*------------------------CreateEventBase------------------------*/
event_base *pBase = event_base_new();
if( NULL == pBase )
{
printf("Client Create Event Base Error!\n");
return -1;
}


/*------------------------CreateEvent------------------------*/
event*pEvent = event_new(pBase,fd,EV_READ|EV_PERSIST,OnClientRead,NULL);
if( NULL == pEvent )
{
printf("Client Create Event Failed!\n");
return -1;
}


/*------------------------Add Event To List------------------------*/
event_add(pEvent,NULL);




/*------------------------EventLoop------------------------*/
event_base_dispatch(pBase);

return 0;

}

void OnClientRead(int fd,short narg,void *pParam )
{

char szMsg[MAX_READ_MSG_LEN] = { 0 };
int nLen = read(fd, szMsg, MAX_READ_MSG_LEN-1);
if( nLen <= 0 )
{
printf("OnClientRead failed of read message!\n");
return;
}

szMsg[nLen] = '\0';

printf("OnClientRead read msg=%s\n", szMsg);

}

18.1.2服务器端

 

server.c

/*Author:ZhouYong
http://blog.csdn.net/zhouyongku
Date:2016-11-29*/
#include<stdio.h>
#include<stdlib.h>
#include <unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<event2/event.h>

#define MAX_LISTEN_SOCKET_NUM1024
#define MAX_SEND_MSG_LEN4096
constshortg_nConnectPort = 15623;

void OnAccept( int fdListener,short nArg,void *pParam );

int main()
{

/*------------------------Bind socket and listen------------------------*/
sockaddr_in addr;
addr.sin_addr.s_addr= 0;
addr.sin_family = PF_INET;
addr.sin_port = htons(g_nConnectPort);

int fdListener = socket(PF_INET,SOCK_STREAM,0);

if( fdListener<0 )
{
printf("Server Create Socket Error!\n");
return -1;
}


if( bind(fdListener,(sockaddr*)&addr,sizeof(addr)) <0 )
{
printf("Server bind Socket Error!\n");
return -1;
}

if( listen(fdListener,MAX_LISTEN_SOCKET_NUM) <0 )
{
printf("Server listen Error!\n");
return -1;
}


/*------------------------Create eventbase------------------------*/
event_base *pBase = event_base_new();
if( NULL == pBase )
{
printf("Server Create Event Base Error!\n");
return -1;
}

/*------------------------CreateEvent------------------------*/
event*pEvent = event_new(pBase,fdListener,EV_READ|EV_PERSIST,OnAccept,pBase);
if( NULL == pEvent )
{
printf("Server Create Event Failed!\n");
return -1;
}



/*------------------------Add Event To List------------------------*/
event_add(pEvent,NULL);




/*------------------------EventLoop------------------------*/
event_base_dispatch(pBase);

return 0;


}


void OnAccept( int fdListener,short nArg,void *pParam )
{
if( NULL == pParam ) return;

event_base *pBase = (event_base*)pParam;


evutil_socket_t fdClient;
struct sockaddr_in addrClient;
socklen_t nAddrLen;

fdClient = accept(fdListener, (sockaddr*)&addrClient, &nAddrLen );
if( fdClient <0 )
{
printf("Server OnAccept failed of accept!");
return;
}

evutil_make_socket_nonblocking(fdClient);

printf("Server accept socket =%d!\n",fdClient);

//event *pEvent = event_new(pBase,fdClient,EV_READ|EV_PERSIST,......


}

 

18.1.3编译源码

编译

[root@localhost Test2]# g++ -c client.c 
[root@localhost Test2]# g++ -levent client.o -o client
[root@localhost Test2]# g++ -c server.c
[root@localhost Test2]# g++ -levent server.o -o server

 

18.1.4脚本文件

批量运行脚本

[root@localhost Test2]# vi run.sh
#!/bin/bash
for i in $(seq 1 100 )
do
./client &

done

18.1.4运行测试

运行服务端

[root@localhost Test2]# rm -rf *.o
[root@localhost Test2]# ll
total 44
-rwxr-xr-x. 1 root root 13340 Nov 29 22:33 client
-rw-r--r--. 1 root root 2156 Nov 29 21:45 client.c
-rw-r--r--. 1 root root 61 Nov 29 22:19 run.sh
-rwxr-xr-x. 1 root root 13239 Nov 29 22:34 server
-rw-r--r--. 1 root root 2267 Nov 29 22:12 server.c
[root@localhost Test2]# ./server


批量运行客户端

[root@localhost Test2]# sh run.sh 
Client Connect To Server ip=127.0.0.1 port=15623 success!
Client Connect To Server ip=127.0.0.1 port=15623 success!
Client Connect To Server ip=127.0.0.1 port=15623 success!
Client Connect To Server ip=127.0.0.1 port=15623 success!
Client Connect To Server ip=127.0.0.1 port=15623 success!
Client Connect To Server ip=127.0.0.1 port=15623 success!
Client Connect To Server ip=127.0.0.1 port=15623 success!
Client Connect To Server ip=127.0.0.1 port=15623 success!
Client Connect To Server ip=127.0.0.1 port=15623 success!
Client Connect To Server ip=127.0.0.1 port=15623 success!
Client Connect To Server ip=127.0.0.1 port=15623 success!
Client Connect To Server ip=127.0.0.1 port=15623 success!
Client Connect To Server ip=127.0.0.1 port=15623 success!
Client Connect To Server ip=127.0.0.1 port=15623 success!
Client Connect To Server ip=127.0.0.1 port=15623 success!
Client Connect To Server ip=127.0.0.1 port=15623 success!
Client Connect To Server ip=127.0.0.1 port=15623 success!
Client Connect To Server ip=127.0.0.1 port=15623 success!
Client Connect To Server ip=127.0.0.1 port=15623 success!
Client Connect To Server ip=127.0.0.1 port=15623 success!
Client Connect To Server ip=127.0.0.1 port=15623 success!
Client Connect To Server ip=127.0.0.1 port=15623 success!
Client Connect To Server ip=127.0.0.1 port=15623 success!
Client Connect To Server ip=127.0.0.1 port=15623 success!

服务器反馈

[root@localhost Test2]# ./server 
Server accept socket =7!
Server accept socket =8!
Server accept socket =9!
Server accept socket =10!
Server accept socket =11!
Server accept socket =12!
Server accept socket =13!
Server accept socket =14!
Server accept socket =15!
Server accept socket =16!
Server accept socket =17!
Server accept socket =18!
Server accept socket =19!
Server accept socket =20!
Server accept socket =21!

性能观察

[root@localhost Test2]# top
top - 22:41:26 up 1:59, 6 users, load average: 0.04, 0.05, 0.13
Tasks: 424 total, 2 running, 422 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.0 us, 0.2 sy, 0.0 ni, 99.8 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 3874956 total, 2739080 free, 644724 used, 491152 buff/cache
KiB Swap: 2097148 total, 2097148 free, 0 used. 2969920 avail Mem

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
3001 root 20 0 252412 1492 1080 S 0.7 0.0 0:33.81 pcscd
1002 root 20 0 243868 6316 4808 S 0.3 0.2 0:09.48 vmtoolsd
3498 zhouyong 20 0 1168896 24696 16296 S 0.3 0.6 0:17.31 gnome-settings-
3748 zhouyong 20 0 144768 3360 2520 S 0.3 0.1 0:16.37 escd
6600 root 20 0 143828 6124 3884 S 0.3 0.2 0:22.44 sshd
1 root 20 0 192088 7388 2616 S 0.0 0.2 0:05.42 systemd
2 root 20 0 0 0 0 S 0.0 0.0 0:00.04 kthreadd
3 root 20 0 0 0 0 S 0.0 0.0 0:00.19 ksoftirqd/0
5 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 kworker/0:0H
6 root 20 0 0 0 0 S 0.0 0.0 0:00.01 kworker/u128:0
7 root rt 0 0 0 0 S 0.0 0.0 0:00.24 migration/0
8 root 20 0 0 0 0 S 0.0 0.0 0:00.00 rcu_bh
9 root 20 0 0 0 0 S 0.0 0.0 0:00.00 rcuob/0
10 root 20 0 0 0 0 S 0.0 0.0 0:00.00 rcuob/1

18.2BufferEvent客户端服务器示例

18.2.1客户端

client.c

/*Author:ZhouYong
http://blog.csdn.net/zhouyongku
Date:2016-11-29
*/
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<event2/event.h>
#include<event2/bufferevent.h>

#define MAX_READ_MSG_LEN4096

const char * g_szServerIP = "127.0.0.1";
constshortg_nConnectPort = 15623;
constchar * g_szWellcomeMsg="This is bufferevent test client demo.\n";
constchar*g_szUserMsg="Hi,I'm client with bufferevent!\n";

//Wait For data in buffer is ready to read,then call the callback fun.
void OnRead(bufferevent *pBufEvent,void *pParam );

//Wait For buffer can write now,then call the callback fun.
void OnWrite(bufferevent *pBufEvent,void *pParam );

//Wait while some event happen to the socket,then call the callback fun.
void OnEvent(bufferevent *pBufEvent,short nEventType,void *pParam );

int main()
{

printf(g_szWellcomeMsg);

/*----------Use Bufferevent to connect server--------------*/

sockaddr_in addr;
inet_aton(g_szServerIP,&addr.sin_addr);
addr.sin_port = htons(g_nConnectPort);
addr.sin_family = PF_INET;

event_base *pBase = event_base_new();
if( NULL == pBase )
{
printf("Client Create Event Base Error!\n");
return -1;
}

bufferevent *pBufEvent;

//recv an close message
pBufEvent = bufferevent_socket_new(pBase,-1,BEV_OPT_CLOSE_ON_FREE);
if( NULL == pBufEvent )
{
printf("Client bufferevent_socket_new Error!\n");
return -1;
}

bufferevent_setcb(pBufEvent,OnRead,OnWrite,OnEvent,NULL);
bufferevent_enable(pBufEvent, EV_READ | EV_WRITE | EV_PERSIST);

if (bufferevent_socket_connect(pBufEvent,(sockaddr* )&addr,sizeof(addr)) < 0)
{
printf("Client bufferevent_socket_connect Error!\n");
bufferevent_free(pBufEvent);
return -1;
}

printf("Server bufferevent_socket_connect ip=%s port=%d success!\n",g_szServerIP,g_nConnectPort);

bufferevent_write(pBufEvent,g_szUserMsg,strlen(g_szUserMsg)+1);

event_base_dispatch(pBase);

return 0;

}

void OnRead(bufferevent *pBufEvent,void *pParam )
{
printf("client OnRead!\n");
char szMsg[MAX_READ_MSG_LEN] = { 0 };

int nLen = bufferevent_read(pBufEvent,szMsg,MAX_READ_MSG_LEN );
if( nLen >0 )
{
printf("Client OnRead Msg=[%s]\n",szMsg);
}
}
void OnWrite(bufferevent *pBufEvent,void *pParam )
{
printf("client OnWrite!\n");

}
void OnEvent(bufferevent *pBufEvent,short nEventType,void *pParam )
{

if (nEventType & BEV_EVENT_EOF)
{
printf("OnEvent connection closed\n");
bufferevent_free(pBufEvent);
}
else if ( nEventType &BEV_EVENT_CONNECTED )
{
printf("OnEvent connect to server success!\n");
}
else if (nEventType & BEV_EVENT_ERROR)
{
printf("OnEvent meet some other error\n");
}
else
{
//TODO:......
}

}

 

18.2.2服务器端

 

server.c

/*Author:ZhouYong
http://blog.csdn.net/zhouyongku
Date:2016-11-29
*/
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<event2/event.h>
#include<event2/bufferevent.h>
#include<event2/util.h>
#include<event2/listener.h>

#define MAX_READ_MSG_LEN4096
#define MAX_LISTEN_SOCKET_NUM1024
const char * g_szServerIP = "127.0.0.1";
constshortg_nConnectPort = 15623;
constchar * g_szWellcomeMsg="This is bufferevent test Server demo.\n";
constchar*g_szUserMsg="Hi,I'm Server with bufferevent!\n";


//Wait for an socket connect in,then call the callback fun
void OnAccept(evconnlistener *listener, evutil_socket_t fdClient,
sockaddr *pAddr, int nSocklen, void *pParam);

//Wait For data in buffer is ready to read,then call the callback fun.
void OnRead(bufferevent *pBufEvent,void *pParam );

//Wait For buffer can write now,then call the callback fun.
void OnWrite(bufferevent *pBufEvent,void *pParam );

//Wait while some event happen to the socket,then call the callback fun.
void OnEvent(bufferevent *pBufEvent,short nEventType,void *pParam );


int main()
{

printf(g_szWellcomeMsg);


sockaddr_in addr;
addr.sin_addr.s_addr = 0;
addr.sin_port = htons(g_nConnectPort);
addr.sin_family = PF_INET;

event_base *pBase = event_base_new();
if( NULL == pBase )
{
printf("Server Create Event Base Error!\n");
return -1;
}


evconnlistener *pEvListener = evconnlistener_new_bind(pBase,
OnAccept,
pBase,
LEV_OPT_REUSEABLE|LEV_OPT_CLOSE_ON_FREE,
MAX_LISTEN_SOCKET_NUM,
(sockaddr*)&addr,
sizeof(addr));
if( NULL == pEvListener )
{
event_base_free(pBase);
printf("Server evconnlistener_new_bind failed!\n");
return -1;
}
event_base_dispatch(pBase);

evconnlistener_free(pEvListener);

event_base_free(pBase);

return 0;

}

void OnAccept(evconnlistener *listener, evutil_socket_t fdClient,
sockaddr *pAddr, int nSocklen, void *pParam)
{
if( NULL == pParam || NULL == pAddr ) return ;

/*const char *const strIP = inet_ntoa(pAddr->sa_data);

if( NULL == strIP )
{
printf("Server OnAccept meet an error!\n");
return ;
}*/

printf("Server OnAccept an socket ip=%s,id=%d\n", pAddr->sa_data,fdClient);

event_base *pBase = (event_base*)pParam;

//*-----------Allocate a bufferevent for client connection-----------*/
bufferevent *pBufEvent = bufferevent_socket_new(pBase,
fdClient,
BEV_OPT_CLOSE_ON_FREE);
if( NULL == pBufEvent )
{
printf("Server bufferevent_socket_new Error!\n");
return;
}
bufferevent_setcb(pBufEvent, OnRead, OnWrite, OnEvent, NULL);
bufferevent_enable(pBufEvent, EV_READ | EV_WRITE| EV_PERSIST);


}


void OnRead(bufferevent *pBufEvent,void *pParam )
{
printf("Server OnRead!\n");
char szMsg[MAX_READ_MSG_LEN] = { 0 };

int nLen = bufferevent_read(pBufEvent,szMsg,MAX_READ_MSG_LEN );
if( nLen >0 )
{
printf("Server OnRead Msg=[%s]\n",szMsg);
}
bufferevent_write(pBufEvent,g_szUserMsg,strlen(g_szUserMsg)+1);
}
void OnWrite(bufferevent *pBufEvent,void *pParam )
{
printf("Server OnWrite!\n");

}
void OnEvent(bufferevent *pBufEvent,short nEventType,void *pParam )
{

if (nEventType & BEV_EVENT_EOF)
{
printf("OnEvent connection closed\n");
//这将自动close套接字和free读写缓冲区
bufferevent_free(pBufEvent);
}
else if ( nEventType &BEV_EVENT_CONNECTED )
{
printf("OnEvent connect to server success!\n");
}
else if (nEventType & BEV_EVENT_ERROR)
{
printf("OnEvent meet some other error\n");
}
else
{
//TODO:......
}

}

 

18.2.3编译源码

18.1.3

18.2.4脚本文件

18.1.4

18.2.4运行测试

运行服务端

[root@localhost Test3]# ./server 
This is bufferevent test Server demo.
Server OnAccept an socket ip=,id=7
Server OnRead!
Server OnRead Msg=[Hi,I'm client with bufferevent!
]
Server OnWrite!

 

运行客户端

[root@localhost Test3]# ./client 
This is bufferevent test client demo.
Server bufferevent_socket_connect ip=127.0.0.1 port=15623 success!
OnEvent connect to server success!
client OnWrite!
client OnRead!
Client OnRead Msg=[Hi,I'm Server with bufferevent!