当前位置: 首页 > article >正文

Libevent实现TCP客户端服务器

Libevent实现TCP客户端服务器

17-libevent实现Tcp服务器流程_bilibili_哔哩哔哩_bilibili

文章目录

  • Libevent实现TCP客户端服务器
    • 1.服务器端实现流程
    • 2.服务器端代码实现
    • 3.客户端实现流程
    • 4.客户端代码实现

1.服务器端实现流程

1.创建 event_base

2.创建服务器连接监听器 evconnlister_new_bind() ;

3.在 evconnlister_new_bind 的回调函数中,处理接受连接后的操作

4.回调函数被调用,说明有一个新客户端连接上来。会得到一个新fd,用于跟客户端通信(读、写)

5.使用 bufferevnet_socket_new()创建一个新bufferevnet事件,将fd 封装到这个事件对象中

6.使用 bufferevent_setcb 给这个事件对象的 read、write、event 设置回调

7.设置 bufferevnet 的读写缓冲区 enable/disable

8.接受、发送数据 bufferevent_read()/bufferevent_write()

9.启动循环监听

10.释放资源

2.服务器端代码实现

#include<event2/listener.h>
#include<event2/bufferevent.h>
#include<event2/event.h>
#include<sys/epoll.h>
#include<sys/select.h>
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<fcntl.h>
#include<errno.h>
#include<string.h>
#include<dirent.h>
#include<sys/stat.h>
#include<wait.h>
#include<sys/mman.h>
#include<signal.h>
#include<pthread.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<ctype.h>
#include<strings.h>
#include<netinet/ip.h>
#define SERV_PORT 9527
//读回调
void read_cb(struct bufferevent *bev,void *arg)
{
	char buf[1024]={0};
	//替代的是read函数
	bufferevent_read(bev,buf,sizeof(buf));
	printf("client say:%s\n",buf);

	char *p="我是服务器,已经成功收到你发送的数据";
	//写数据给客户端 替代write函数
	bufferevent_write(bev,p,strlen(p)+1);
	sleep(1);
}
//写缓冲区的回调函数比较鸡肋,写缓冲区有数据就自动写给客户端了,写完了才会进行回调
void write_cb(struct bufferevent *bev,void *arg)
{
	//printf("我是服务器,已经成功写数据给客户端,写缓冲区回调函数被回调");
}
//事件回调
void event_cb(struct bufferevent *bev,short events,void *arg)
{
    //读到末尾
	if(events & BEV_EVENT_EOF)
		printf("连接关闭");
    //发生错误
	else if(events&BEV_EVENT_ERROR)
		printf("other error");

	bufferevent_free(bev);

	printf("buffevent 资源已经被释放..\n");
	
}


void cb_listener(
		struct evconnlistener *listener,
		evutil_socket_t fd,//服务器cfd用于连接的文件描述符
		struct sockaddr *addr,//客户端的地址结构
		int len,void *ptr)
{
	printf("connect new client\n");
	//将最开始创建的libevent的框架用ptr传入赋值给base
	struct event_base *base=(struct event_base *)ptr;
	//添加新事件
	struct bufferevent *bev;
	bev=bufferevent_socket_new(base,fd,BEV_OPT_CLOSE_ON_FREE);
	//给bufevent的读写缓冲区设置回调函数
	bufferevent_setcb(bev,read_cb,write_cb,event_cb,NULL);
	//启用bufferevent的读缓冲区,写缓冲区默认是enable的
	bufferevent_enable(bev,EV_READ);

}

int main(int argc,char * argv[])
{
	//初始化服务器套接字
	struct sockaddr_in serv;
	memset(&serv,0,sizeof(serv));
	serv.sin_family=AF_INET;
	serv.sin_port=htons(SERV_PORT);
	serv.sin_addr.s_addr=htonl(INADDR_ANY);
	//创建event_base
	struct event_base* base;
	base=event_base_new();
	
	//创建监听器
	struct evconnlistener *listener;
	//参数3设置base
	listener=evconnlistener_new_bind(base,cb_listener,base,
			LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE,36,//最大连接数量
			(struct sockaddr *)&serv,sizeof(serv));
	//启动循环监听
	event_base_dispatch(base);
	//释放和销毁
	evconnlistener_free(listener);
	event_base_free(base);

	return 0;
}

运行结果:
image-20241217230949369

3.客户端实现流程

1.创建 event_base

2.使用 bufferevnet_socket_new()创建一个用跟服务器通信的 bufferevnet 事件对象+

3.使用 bufferevnet_socket_connect()连接 服务器

4.使用 bufferevent_setcb()给 bufferevnet 对象的 read、write、event 设置回调

5.设置 bufferevnet 对象的读写缓冲区 enable/disable

6.接受、发送数据 bufferevent_read()/bufferevent_write()

7.释放资源

4.客户端代码实现

#include<event2/listener.h>
#include<event2/bufferevent.h>
#include<event2/event.h>
#include<sys/epoll.h>
#include<sys/select.h>
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<fcntl.h>
#include<errno.h>
#include<string.h>
#include<dirent.h>
#include<sys/stat.h>
#include<wait.h>
#include<sys/mman.h>
#include<signal.h>
#include<pthread.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<ctype.h>
#include<strings.h>
#include<netinet/ip.h>
#define SERV_PORT 9527

void read_cb(struct bufferevent *bev, void *arg)
{
    char buf[1024] = {0}; 
    bufferevent_read(bev, buf, sizeof(buf));

    printf("fwq say:%s\n", buf);

    bufferevent_write(bev, buf, strlen(buf)+1);
    sleep(1);
}

void write_cb(struct bufferevent *bev, void *arg)
{
   // printf("----------我是客户端的写回调函数,没卵用\n"); 
}

void event_cb(struct bufferevent *bev, short events, void *arg)
{
    if (events & BEV_EVENT_EOF)
    {
        printf("connection closed\n");  
    }
    else if(events & BEV_EVENT_ERROR)   
    {
        printf("some other error\n");
    }
    else if(events & BEV_EVENT_CONNECTED)
    {
        printf("已经连接服务器...\\(^o^)/...\n");
        return;
    }
    
    // 释放资源
    bufferevent_free(bev);
}

//从终端读然后写给服务器
void read_terminal(evutil_socket_t fd,short what,void *arg)
{
	//读数据
	char buf[1024]={0};
	int len=read(fd,buf,sizeof(buf));

	struct bufferevent *bev=(struct bufferevent*)arg;
	//发送数据写给服务器	
	bufferevent_write(bev,buf,len+1);

}

int main(int argc,char * argv[])
{
	struct event_base * base=NULL;
	base=event_base_new();
	//通信用的文件描述符
	int fd=socket(AF_INET,SOCK_STREAM,0);
	//fd封装到buffevent里面
	struct bufferevent *bev=NULL;
	bev=bufferevent_socket_new(base,fd,BEV_OPT_CLOSE_ON_FREE);
	
	struct sockaddr_in serv;
	memset(&serv,0,sizeof(serv));
	serv.sin_family=AF_INET;
	serv.sin_port=htons(9527);
	inet_pton(AF_INET,"127.0.0.1",&serv.sin_addr.s_addr);

	//连接服务器
	bufferevent_socket_connect(bev,(struct sockaddr*)&serv,
			sizeof(serv));
	//设置回调函数
	bufferevent_setcb(bev,read_cb,write_cb,event_cb,NULL);
	//设置读回调生效
	bufferevent_enable(bev,EV_READ);
	//创建事件 从键盘读入客户端写入的内容 加入到base里面一起监听
	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;
}

运行结果:

image-20241217231300384


http://www.kler.cn/a/440866.html

相关文章:

  • 分布式链路追踪-02-Dapper 论文介绍
  • 《红队和蓝队在网络安全中的定义与分工》
  • HarmonyOS 非线性容器LightWeightMap 常用的几个方法
  • 学习笔记:Verilog连续赋值及在线仿真
  • React Native状态管理器Redux、MobX、Context API、useState
  • RPC 服务与 gRPC 的入门案例
  • Docker的存储卷
  • 鸿蒙Next MVVM思想总结
  • 渗透测试之js利用
  • Redis查询占用空间最大的10个key
  • 在pycharm2024.3.1中配置anaconda3-2024-06环境
  • 005 Qt常用控件Qwidget_下
  • 【研究趋势】Nips2024 多模态论文热点分析
  • Anaconda更改虚拟环境安装路径
  • RPC远程服务调用详解和gRPC简介
  • 【合作原创】使用Termux搭建可以使用的生产力环境(七)
  • springmvc跳转不经过视图解析器,controller保存数据,controller层返回json数据,拦截器,全局异常处理,文件上传含本地和阿里oss
  • Fscan内网横向工具
  • Ansible Playbook 简介
  • 三维移动游戏