libevent学习一:编译以及测试使用

  1. 下载地址:http://libevent.org/ ,下载版本:libevent-2.0.22-stable.tar.gz
  2. 解压, 目录为...\libevent-2.0.22-stable(自己的目录)
  3. 修改以下三个文件,添加宏定义:

    在以下3个文件开头添加“#define _WIN32_WINNT 0x0500”

    libevent-2.0.21-stable\event_iocp.c

    libevent-2.0.21-stable\evthread_win32.c

    libevent-2.0.21-stable\listener.c

  4. 打开VS2015命令工具,切换到解压后的libevent目录,然后执行nmake /f Makefile.nmake命令进行编译,命令如下图所示,

           先输入cd/d D:\aa_zhj\a_work\projects\libevent\libevent-2.0.22-stable切换目录,然后输入nmake /f Makefile.nmake进行编译。

    

 

编译成功后再libevent-2.0.22-stable目录下生成三个lib文件:

libevent.lib、libevent_core.lib、libevent_extras.lib

 

5.VS2015下使用lib

新建一个VC++控制台项目:

环境配置:

项目下建一个Lib目录,将上面三个lib文件copy到该目录下。

新建一个Include目录,将libevent-2.0.21-stable\include文件夹下的所有内容和WIN32-Code文件夹下的所有内容拷贝到新建的include目录下,两个event2目录下的文件可合并在一起。

6.项目属性设置

VC++目录:

包含目录,添加上面的Include目录;

库目录,添加上面的Lib目录;

 

 

C/C++:

代码生成-->运行库:多线程调试 (/MTd)(Debug下),多线程 (/MT)(Release下)

连接器:

输入:ws2_32.lib;wsock32.lib;libevent.lib;libevent_core.lib;libevent_extras.lib;

ws2_32.lib;wsock32.lib;是用来编译Windows网络相关的程序库。

高级-->编译为:编译为C++代码(/TP),(因为我的工程用到C++的函数所以配置这个)

网上有人推荐配置成TC的也可以,自己根据项目需要

 

 

配置忽略项,可以不配置

输入\忽略特定默认库 libc.lib;msvcrt.lib;libcd.lib;libcmtd.lib;msvcrtd.lib;%(IgnoreSpecificDefaultLibraries)

 

7. 生成lib后,不带调试信息,无法单步进函数里,所以要修改脚本:Makefile.nmake第二行

CFLAGS=$(CFLAGS) /Od /W3 /wd4996 /nologo /Zi

 

到此为止项目配置好了,我们来写相关的demo代码

#include <stdio.h>
#include <time.h>
#include <io.h>
#include <process.h>
#include <WinSock2.h>
#pragma comment(lib,"ws2_32.lib")

#include <event2/bufferevent.h>
#include <event2/buffer.h>
#include <event2/listener.h>
#include <event2/util.h>
#include <event2/event.h>

#pragma warning(disable:4996)

#define MAX_LINE    256  

void read_cb(struct bufferevent *bev, void *arg) {
	struct evbuffer *buf = (struct evbuffer *)arg;
	char line[MAX_LINE + 1];
	int n;
	evutil_socket_t fd = bufferevent_getfd(bev);
	while (n = bufferevent_read(bev, line, MAX_LINE), n > 0) {
		line[n] = '\0';

		//将读取到的内容放进缓冲区  
		evbuffer_add(buf, line, n);

		//搜索匹配缓冲区中是否有==,==号来分隔每次客户端的请求  
		const char *x = "==";
		struct evbuffer_ptr ptr = evbuffer_search(buf, x, strlen(x), 0);
		if (ptr.pos != -1) {
			bufferevent_write_buffer(bev, buf); //使用buffer的方式输出结果  
		}
	}
}
void write_cb(struct bufferevent *bev, void *arg) {}
void error_cb(struct bufferevent *bev, short event, void *arg) {
	evutil_socket_t fd = bufferevent_getfd(bev);
	printf("fd = %u, ", fd);
	if (event & BEV_EVENT_TIMEOUT) {
		printf("Timed out\n");
	}
	else if (event & BEV_EVENT_EOF) {
		printf("connection closed\n");
	}
	else if (event & BEV_EVENT_ERROR) {
		printf("some other error\n");
	}
	//清空缓冲区  
	struct evbuffer *buf = (struct evbuffer *)arg;
	evbuffer_free(buf);
	bufferevent_free(bev);
}

//回调函数,用于监听连接进来的客户端socket  
void do_accept(evutil_socket_t fd, short event, void *arg) {
	int client_socketfd;//客户端套接字      
	struct sockaddr_in client_addr; //客户端网络地址结构体     
	int in_size = sizeof(struct sockaddr_in);
	//客户端socket    
	client_socketfd = accept(fd, (struct sockaddr *) &client_addr, &in_size); //等待接受请求,这边是阻塞式的    
	if (client_socketfd < 0) {
		puts("accpet error");
		exit(1);
	}

	//类型转换  
	struct event_base *base_ev = (struct event_base *) arg;

	//socket发送欢迎信息    
	char * msg = "Welcome to My socket";
	int size = send(client_socketfd, msg, strlen(msg), 0);

	//创建一个事件,这个事件主要用于监听和读取客户端传递过来的数据  
	//持久类型,并且将base_ev传递到do_read回调函数中去  
	//struct event *ev;  
	//ev = event_new(base_ev, client_socketfd, EV_TIMEOUT|EV_READ|EV_PERSIST, do_read, base_ev);  
	//event_add(ev, NULL);  

	//创建一个evbuffer,用来缓冲客户端传递过来的数据  
	struct evbuffer *buf = evbuffer_new();
	//创建一个bufferevent  
	struct bufferevent *bev = bufferevent_socket_new(base_ev, client_socketfd, BEV_OPT_CLOSE_ON_FREE);
	//设置读取方法和error时候的方法,将buf缓冲区当参数传递  
	bufferevent_setcb(bev, read_cb, NULL, error_cb, buf);
	//设置类型  
	bufferevent_enable(bev, EV_READ | EV_WRITE | EV_PERSIST);
	//设置水位  
	bufferevent_setwatermark(bev, EV_READ, 0, 0);
}


//入口主函数  
int main() {

	WORD sockVersion = MAKEWORD(2, 2);
	WSADATA wsaData;
	if (WSAStartup(sockVersion, &wsaData) != 0)
	{
		return 0;
	}

	int server_socketfd; //服务端socket    
	struct sockaddr_in server_addr;   //服务器网络地址结构体      
	memset(&server_addr, 0, sizeof(server_addr)); //数据初始化--清零      
	server_addr.sin_family = AF_INET; //设置为IP通信      
	server_addr.sin_addr.s_addr = INADDR_ANY;//服务器IP地址--允许连接到所有本地地址上      
	server_addr.sin_port = htons(8001); //服务器端口号      

	//创建服务端套接字    
	server_socketfd = socket(PF_INET, SOCK_STREAM, 0);
	if (server_socketfd < 0) {
		puts("socket error");
		return 0;
	}

	evutil_make_listen_socket_reuseable(server_socketfd); //设置端口重用  
	evutil_make_socket_nonblocking(server_socketfd); //设置无阻赛  

	//绑定IP    
	if (bind(server_socketfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) < 0) {
		puts("bind error");
		return 0;
	}

	//监听,监听队列长度 5    
	listen(server_socketfd, 10);

	//创建event_base 事件的集合,多线程的话 每个线程都要初始化一个event_base  
	struct event_base *base_ev;
	base_ev = event_base_new();
	const char *x = event_base_get_method(base_ev); //获取IO多路复用的模型,linux一般为epoll  
	printf("METHOD:%s\n", x);

	//创建一个事件,类型为持久性EV_PERSIST,回调函数为do_accept(主要用于监听连接进来的客户端)  
	//将base_ev传递到do_accept中的arg参数  
	struct event *ev;
	ev = event_new(base_ev, server_socketfd, EV_TIMEOUT | EV_READ | EV_PERSIST, do_accept, base_ev);

	//注册事件,使事件处于 pending的等待状态  
	event_add(ev, NULL);

	//事件循环  
	event_base_dispatch(base_ev);

	//销毁event_base  
	event_base_free(base_ev);
	return 1;
}

编译,生成!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值