当前位置:   article > 正文

libevent库bufferevent事件实现socket通信_bufferevent_socket_connect

bufferevent_socket_connect

一、基础API

1. 添加 bufferevent 事件
struct bufferevent *bufferevent_socket_new(struct event_base *base, 
					evutil_socket_t fd, 
					enum bufferevent_options options);
  • 1
  • 2
  • 3

base: event_base
fd: 封装bufferevent内的 通信文件描述符fd
options:BEV_OPT_CLOSE_ON_FREE (释放资源)
成功:bufferevent 指针; 失败:NULL

2. 给读写缓冲区设置回调
void bufferevent_setcb(struct bufferevent *bufev,
				bufferevent_data_cb readcb,
				bufferevent_data_cb writecb,
				bufferevent_event_cb eventcb,
				void *cbarg);
  • 1
  • 2
  • 3
  • 4
  • 5

bufev: bufferevent_socket_new() 返回值
readcb: 设置 bufferevent 读缓冲,对应回调 read_cb() { bufferevent_read() 读数据 }
writecb: 设置 bufferevent 写缓冲,对应回调 write_cb(){ 给调用者,发送写成功通知} (可传 NULL)
eventcb: 设置 事件回调。 (可传NULL)
cbarg: 上述回调函数使用的 参数

读回调函数原型:

typedef void (*bufferevent_data_cb)(struct bufferevent *bev, void *cbarg);

void read_cb(struct bufferevent *bev, void *cbarg )
{
		.....
		bufferevent_read();   //read()不能使用,用其替代
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

bufferevent_read() 函数原型:

size_t bufferevent_read(struct bufferevent *bev, void *buf, size_t bufsize);
  • 1

写回调函数原型:

void write_cb(struct bufferevent *bev, void *cbarg);
  • 1

bufferevent_write() 函数原型:

int bufferevent_write(struct bufferevent *bufev, const void *data,  size_t size); 
  • 1

event 回调函数原型:

typedef void (*bufferevent_event_cb)(struct bufferevent *bev,  short events, void *cbarg);

void event_cb(struct bufferevent *bev,  short events, void *cbarg)
{
	......
}

events: BEV_EVENT_CONNECTED (连接客户端成功事件标志)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
3. 启动、关闭 bufferevent 的缓冲区

默认、write 缓冲区开启、read 缓冲区关闭

启动 :

void bufferevent_enable(struct bufferevent *bufev, short events);   
  • 1

关闭:

void bufferevent_diable(struct bufferevent *bufev, short events);   
  • 1

events: EV_READ、EV_WRITE、EV_READ|EV_WRITE

short bufferevent_get_enabled(struct bufferevent *bufev);
获取缓冲区的状态,需要借助 & 来得到
  • 1
  • 2
4. 客户端连接服务器
int bufferevent_socket_connect(struct bufferevent *bev, 
				struct sockaddr *address, int addrlen);
  • 1
  • 2

address、len: connect() 参2/3

5. 服务端创建监听
struct evconnlistener *evconnlistener_new_bind (	
				struct event_base *base,
				evconnlistener_cb cb, 
				void *ptr, 
				unsigned flags,
				int backlog,
				const struct sockaddr *sa,
				int socklen);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

base: event_base
cb: 回调函数。 一旦被回调,说明在其内部应该与客户端完成, 数据读写操作,进行通信
ptr: 回调函数的参数
flags: LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE
backlog: listen() 2参。 -1 表最大值
sa:服务器自己的地址结构体
socklen:服务器自己的地址结构体大小
返回值:成功创建的监听器

typedef void (*evconnlistener_cb)(
				struct evconnlistener *listener,
				evutil_socket_t sock,
				struct sockaddr *addr,
				int len,
				void *ptr);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

listener: evconnlistener_new_bind 函数返回值
sock: 用于通信的文件描述符
addr: 客户端的 IP+端口
len: addr的长度
ptr:外部 ptr 传递进来的值

二、bufferevent 事件开发框架

服务器端:

1. 创建event_base	event_base_new();

2. 创建连接监听器	evconnlistener_new_bind();
	进行绑定地址端口设置最大监听数
	设置监听回调函数
	该函数会创建监听事件添加到event_base中进行监听连接
	当有连接成功接入,就会回调监听回调函数
	
	* 设置监听函数
		- 创建 bufferevent事件绑定通信描述符,进行通信		bufferevent_socket_new();
		- 设置 bufferevent事件设置读、写、其他事件回调函数	bufferevent_setcb();
			读函数bufferevent_read(); 写函数bufferevent_write()- 使能 读写缓冲区	bufferevent_enable(); 

3. 执行 event_base	event_base_dispatch();

4. 资源释放		evconnlistener_free(); event_base_free();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

客户端

  1. 创建event_base
  2. 创建bufferevent事件
  3. 使用bufferevnet_socket_connect()连接服务器
  4. bufferevent事件的 read、write、event 事件设置回调函数
  5. 设置读缓冲、写缓冲的 使能状态
  6. 接受、发送数据 bufferevent_read() / bufferevent_write()
  7. 启动事件循环 event_base_dispatch()
  8. 释放资源

三、示例

服务端:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <event2/event.h>
#include <event2/bufferevent.h>
#include <event2/listener.h>

#define PROT 8888

void write_cb(struct bufferevent *bev, void *cbarg)
{
	printf("send successful...\n");
}

void read_cb(struct bufferevent *bev, void *cbarg)
{
	char buf[128] = {0};

	bufferevent_read(bev, buf, sizeof(buf));
	fputs(buf, stdout);
	bufferevent_write(bev, "Data received successfully\n", 32);
}

void event_cb(struct bufferevent *bev, short events, void *cbarg)
{
	//其他事件 处理
}

void cb_listener(
		struct evconnlistener *listener,
		evutil_socket_t fd,
		struct sockaddr *addr,
		int len, void *base)
{
	//添加bufferevent事件 绑定通信描述符 进行通信
	struct bufferevent *bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);

	// 给bufferevent缓冲区设置回调函数 
	bufferevent_setcb(bev, read_cb, write_cb, event_cb, NULL);
	//读缓冲区使能
	bufferevent_enable(bev, EV_READ);
}

int main(void)
{
	//客户端地址结构
	struct sockaddr_in caddr;
	caddr.sin_family = AF_INET;
	caddr.sin_port   = htons(PROT);
	caddr.sin_addr.s_addr = htonl(INADDR_ANY);
	//创建event_base
	struct event_base *base = event_base_new();	
	//创建监听服务器
	struct evconnlistener *listener = evconnlistener_new_bind(base, cb_listener, base,
			BEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE,
			-1, (struct sockaddr*)&caddr, sizeof(caddr));

	event_base_dispatch(base);

	evconnlistener_free(listener);
	event_base_free(base);

	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66

客户端:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <event2/event.h>
#include <event2/bufferevent.h>
#include <event2/listener.h>

#define PROT 8888

void write_cb(struct bufferevent *bev, void *cbarg)
{
	printf("send successful...\n");
}

void read_cb(struct bufferevent *bev, void *cbarg)
{
	char buf[128] = {0};

	bufferevent_read(bev, buf, sizeof(buf));
	fputs(buf, stdout);
}

void event_cb(struct bufferevent *bev, short events, void *cbarg)
{
	//
}

void read_terminal(evutil_socket_t fd, short what, void *cbarg)
{
	char buf[128] = {0};
	struct bufferevent *bev = (struct bufferevent*)cbarg;	
	//将标准输入写到服务器
	int len = read(STDIN_FILENO, buf, sizeof(buf));	
	bufferevent_write(bev, buf, len);
}

int main(void)
{
	//服务器地址结构
	struct sockaddr_in caddr;
	caddr.sin_family = AF_INET;
	caddr.sin_port   = htons(PROT);
	inet_pton(AF_INET, "127.0.0.1", &caddr.sin_addr);
	
	int fd = socket(AF_INET, SOCK_STREAM, 0);		
	
	struct event_base *base = event_base_new();	
	//添加 bufferevent 事件 绑定通信文件描述符 进行通信
	struct bufferevent *bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);
	//连接到服务器	
	bufferevent_socket_connect(bev, (struct sockaddr*)&caddr, sizeof(caddr));	
	//设置回调函数
	bufferevent_setcb(bev, read_cb, write_cb, event_cb, NULL);	
	//使能读缓冲区
	bufferevent_enable(bev, EV_READ);
	//添加 event事件 读标准输入并写到服务器
	struct event *ev = event_new(base, STDIN_FILENO, EV_READ|EV_PERSIST, read_terminal, bev);
	event_add(ev, NULL);

	event_base_dispatch(base);

	event_free(ev);
	event_base_free(base);

	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/527091
推荐阅读
相关标签
  

闽ICP备14008679号