全国咨询/投诉热线:400-618-9090

首页技术文章正文

C/C++:深入浅出-服务器高并发库libevent(一)

更新时间:2017-11-30 来源:黑马程序员 浏览量:

1、安装

libevent是一个开源的高并发服务器开发包,官方地址http://libevent.org/

libevent目前有两个版本一个是1.4系列版本,一个是2.0系列版本。

我们可以在官方网站上看到类似 有个stable表示稳定版本。

· libevent-1.4.15-stable.tar.gz

对于初学者学习,建议从1.4版本学起。

在安装libevent之前先判断本电脑是否已经安装了

通过指令

ls -al /usr/lib|grep libevent

如果没有任何信息则表示没有安装,有的话如果发现libevent是1.3以下版本,则可以同过执行 rpm -e libevent —nodeps 进行卸载。如果是其他操作系统使用其他对应卸载指令即可。

对于下好的tar包,通过

tar -zxvf libevent-release-1.4.15-stable.tar.gz

指令解压。

然后执行./configure命令,但是有的包可能没有configure文件,却存在一个

autogen.sh 脚本,运行这个脚本。

(如果运行不起来请安装autoconf包)

然后

./configure –prefix=/usr

make

sudo make install

安装完之后执行

ls -al /usr/lib/|grep libevent

如果发现有libevent文件库存在就代表安装完毕。

2、简单的libevent服务器

我们通过连接libevent库来进行管理libevent库,所以在使用gcc或者g++编译的时候最后需要加上-levent

下面是一个简单的libevent服务器。

#include

#include

#include

#include

#include

#include

#include

#include

#include

using namespace std;

#define SERVER_ADDR "127.0.0.1"

#define SERVER_PORT 8888

// 事件base

struct event_base* base;

// 读事件回调函数

void onRead(int iCliFd, short iEvent, void *arg)

{

int iLen;

char buf[1500];

iLen = recv(iCliFd, buf, 1500, 0);

if (iLen <= 0) {

cout << "Client Close" << endl;

// 连接结束(=0)或连接错误(<0),将事件删除并释放内存空间

struct event *pEvRead = (struct event*)arg;

event_del(pEvRead);

delete pEvRead;

close(iCliFd);

return;

}

buf[iLen] = 0;

cout << "Client Info:" << buf << endl;

struct bufferevent* buf_ev;

buf_ev = bufferevent_new(iCliFd, NULL, NULL, NULL, NULL);

buf_ev->wm_read.high = 4096;

char MESSAGE[]="welcome to server..";

bufferevent_write(buf_ev, MESSAGE, strlen(MESSAGE));

}

// 连接请求事件回调函数

void onAccept(int iSvrFd, short iEvent, void *arg)

{

int iCliFd;

struct sockaddr_in sCliAddr;

socklen_t iSinSize = sizeof(sCliAddr);

iCliFd = accept(iSvrFd, (struct sockaddr*)&sCliAddr, &iSinSize);

// 连接注册为新事件 (EV_PERSIST为事件触发后不默认删除)

struct event *pEvRead = new event;

event_set(pEvRead, iCliFd, EV_READ|EV_PERSIST, onRead, pEvRead);

event_base_set(base, pEvRead);

event_add(pEvRead, NULL);

struct bufferevent* buf_ev;

buf_ev = bufferevent_new(iCliFd, NULL, NULL, NULL, NULL);

buf_ev->wm_read.high = 4096;

char MESSAGE[]="welcome to server..";

bufferevent_write(buf_ev, MESSAGE, strlen(MESSAGE));

cout<<"a client connect:"<<iclifd<<endl;< p="">

}

int main()

{

int iSvrFd;

struct sockaddr_in sSvrAddr;

memset(&sSvrAddr, 0, sizeof(sSvrAddr));

sSvrAddr.sin_family = AF_INET;

sSvrAddr.sin_addr.s_addr = inet_addr(SERVER_ADDR);

sSvrAddr.sin_port = htons(SERVER_PORT);

// 创建tcpSocket(iSvrFd),监听本机8888端口

iSvrFd = socket(AF_INET, SOCK_STREAM, 0);

bind(iSvrFd, (struct sockaddr*)&sSvrAddr, sizeof(sSvrAddr));

listen(iSvrFd, 10);

// 初始化base

base = (struct event_base*)event_init();

struct event evListen;

// 设置事件

event_set(&evListen, iSvrFd, EV_READ|EV_PERSIST, onAccept, NULL);

// 设置为base事件

event_base_set(base, &evListen);

// 添加事件

event_add(&evListen, NULL);

// 事件循环

event_base_dispatch(base);

return 0;

}

通过编译指令

g++ server.cpp -o server -Wall -g -I ./ -levent

得到可执行程序

./server

启动。

如果能够编译成功并且能够正常启动,说明你操作系统的libevent安装时没问题的。

然后可以通过命令

nc 127.0.0.1 8888

来进行测试。

或者编写如下客户端代码:

/******* 客户端程序 client.c ************/

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define SERVER_ADDR "127.0.0.1"

#define SERVER_PORT 8888

int main(int argc, char *argv[])

{

int sockfd;

char buffer[1024];

struct sockaddr_in server_addr;

struct hostent *host;

int portnumber,nbytes;

if((host=gethostbyname(SERVER_ADDR))==NULL)

{

fprintf(stderr,"Gethostname error\n");

exit(1);

}

if((portnumber=SERVER_PORT)<0)

{

fprintf(stderr,"Usage:%s hostname portnumber\a\n",argv[0]);

exit(1);

}

/* 客户程序开始建立 sockfd描述符 */

if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)

{

fprintf(stderr,"Socket Error:%s\a\n",strerror(errno));

exit(1);

}

/* 客户程序填充服务端的资料 */

bzero(&server_addr,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);

/* 客户程序发起连接请求 */

if(connect(sockfd,(struct sockaddr *)(&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 = read(sockfd,buffer,1024))==-1)

{

fprintf(stderr,"read error:%s\n",strerror(errno));

exit(1);

}

buffer[nbytes]='\0';

printf("I have received:%s\n",buffer);

memset(buffer,0,1024);

sleep(2);

}

/* 结束通讯 */

close(sockfd);

exit(0);

}

通过编译指令

g++ client.cpp -o client -Wall -g -I ./ -levent

生成客户端程序client 进行测试。

现在已经可以跑起来一个简单的libevent程序了。那么这些神奇的代码到底是什么含义呢?

期待下一章我们慢慢来分析~~~


本文版权归黑马程序员C/C++学院所有,欢迎转载,转载请注明作者出处。谢谢!


作者:黑马程序员C/C++培训学院


首发:http://c.itheima.com/


javaee

python

web

ui

cloud

test

c

netmarket

pm

Linux

movies

robot

http://www.itcast.cn/subject/uizly/index.shtml?seozxuids

14天免费试学

基础班入门课程限时免费

申请试学名额

15天免费试学

基础班入门课程限时免费

申请试学名额

15天免费试学

基础班入门课程限时免费

申请试学名额

15天免费试学

基础班入门课程限时免费

申请试学名额

20天免费试学

基础班入门课程限时免费

申请试学名额

8天免费试学

基础班入门课程限时免费

申请试学名额

20天免费试学

基础班入门课程限时免费

申请试学名额

5天免费试学

基础班入门课程限时免费

申请试学名额

0天免费试学

基础班入门课程限时免费

申请试学名额

12天免费试学

基础班入门课程限时免费

申请试学名额

5天免费试学

基础班入门课程限时免费

申请试学名额

5天免费试学

基础班入门课程限时免费

申请试学名额

10天免费试学

基础班入门课程限时免费

申请试学名额
在线咨询 我要报名