网络编程-libevnet不带缓冲的事件框架
网络编程-libevnet不带缓冲的事件框架
1.1工作流程
图1 工作流程
常用的API:
分类 |
API |
含义 |
事件 框架 |
struct event_base* event_base_new(void); |
创建事件框架 |
event_base_free(struct event_base* base); |
释放事件框架 |
|
const char *event_base_get_method(const struct event_base *base); |
获取支持的使用IO方法 |
|
事件 |
struct event *event_new(struct event_base *base, evutil_socket_t fd, shord what, event_callback_fn cb, void *arg); |
创建新事件: EV_READ:读 EV_WRITE:写 EV_SIGNAL:信号量EV_PERSIST:持续触发EV_ET://边沿模式 |
void event_free(struct event *event); |
释放事件 |
|
int event_add( struct event *ev, const struct timeval *tv); |
设置未决事件 |
|
int event_del(struct event *ev); |
设置已决事件 |
|
event_base_dispatch(struct event_base* base) |
开始循环 |
|
int event_base_loopexit( struct event_base *base, const struct timeval *tv); |
延迟终止循环(需等待本次事件完成) |
|
int event_base_loopbreak(struct event_base *base); |
立即终止循环 |
先看效果:先开启服务器后开启服务器
这个例子简单的连接,取代传统的socket的编写网络编程,还有就是采用多路IO复用的方式来实现并发,此程序沒有进行优化,比如
- 当首先启动客户端程序的时候,将发生崩溃
- 当停止连接的时候,杀掉服务端,客户端将疯狂输出
- 没有使用的其他的事件服务来优化代码,比如定时器,信号量等,这个主要在带缓存的事件服务框架里
1.2客户端代码
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<errno.h>
#include<unistd.h> #include<stdio.h>
#include<string.h>
#include<stdlib.h> #include<event.h>
#include<event2/bufferevent.h>
#include<event2/buffer.h>
#include<event2/util.h> typedef struct sockaddr SA; typedef struct
{char head[4];unsigned long pack_len;int code;
} msg_header;char buf[50];void read_cb(evutil_socket_t fd, short what, void *arg)
{char buf[1024] = {0};int len = read(fd, buf, sizeof(buf));printf("say:%s\n", buf);sleep(1);
}int tcp_connect_server(const char* server_ip, int port)
{ int sockfd, status, save_errno; struct sockaddr_in server_addr; memset(&server_addr, 0, sizeof(server_addr) ); server_addr.sin_family = AF_INET; server_addr.sin_port = htons(port); status = inet_aton(server_ip, &server_addr.sin_addr); if( status == 0 ) { errno = EINVAL; return -1; } sockfd = socket(PF_INET, SOCK_STREAM, 0); if( sockfd == -1 ) return sockfd; status = connect(sockfd, (SA*)&server_addr, sizeof(server_addr) ); if( status == -1 ) { save_errno = errno; close(sockfd); errno = save_errno;return -1; } evutil_make_socket_nonblocking(sockfd); return sockfd;
} void tcp_send(int sockfd)
{msg_header st1;memcpy(st1.head, "kpr", 4);st1.pack_len = 8;st1.code = 0;memcpy(buf, &st1, sizeof(msg_header));memcpy(buf+sizeof(msg_header),"lishuwei",9);printf("head:%s\n", st1.head);printf("code:%d\n", st1.code);printf("pack_len:%d\n", st1.pack_len);printf("key:%s\n", buf+sizeof(msg_header));if(-1==write(sockfd,buf,sizeof(buf)+1)){printf("socket write error");}
}int start_connct(char* server_ip, int port)
{ printf("msg_header111:%d",sizeof( msg_header));//两个参数依次是服务器端的IP地址、端口号 int sockfd = tcp_connect_server(server_ip, port); if( sockfd == -1) { perror("tcp_connect error "); return -1; } printf("connect to server successful\n"); tcp_send(sockfd);struct event_base* base = NULL;base = event_base_new();// 创建事件struct event* ev = NULL;ev = event_new(base, sockfd, EV_READ | EV_PERSIST, read_cb, NULL);event_add(ev, NULL);event_base_dispatch(base);event_free(ev);event_base_free(base);close(sockfd);printf("finished \n"); return 1;
} int main(int argc,char* argv[])
{start_connct(argv[1],atoi(argv[2]));return 0;
}
1.3 服务器
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "arpa/inet.h"
#include "event.h"
#include <signal.h>typedef struct sockaddr SA;typedef struct
{char head[4];unsigned long pack_len;int code;
} msg_header;void accept_cb(int fd, short events, void* arg);
void socket_read_cb(struct bufferevent* bev, void* arg);
void event_cb(struct bufferevent *bev, short event, void *arg);
int tcp_server_init(int port, int listen_num);int main(int argc, char** argv)
{int listener = tcp_server_init(9999, 10);if( listener == -1 ){perror(" tcp_server_init error ");return -1;}struct event_base* base = event_base_new();struct event* ev_listen = event_new(base, listener, EV_READ | EV_PERSIST,accept_cb, base);event_add(ev_listen, NULL);event_base_dispatch(base);event_base_free(base);return 0;
}void accept_cb(int fd, short events, void* arg)
{evutil_socket_t sockfd;struct sockaddr_in client;socklen_t len = sizeof(client);sockfd = accept(fd, (struct sockaddr*)&client, &len );evutil_make_socket_nonblocking(sockfd);printf("accept a client %d\n", sockfd);struct event_base* base = (struct event_base*)arg;struct bufferevent* bev = bufferevent_socket_new(base, sockfd, BEV_OPT_CLOSE_ON_FREE);bufferevent_setcb(bev, socket_read_cb, NULL, event_cb, arg);bufferevent_enable(bev, EV_READ | EV_PERSIST);
}void socket_read_cb(struct bufferevent* bev, void* arg)
{msg_header st2;char msg[4096];size_t len = bufferevent_read(bev, msg, sizeof(msg));memcpy(&st2, msg, sizeof(msg_header));printf("socket_read_cb head:%s\n", st2.head);printf("socket_read_cb code:%d\n", st2.code);printf("socket_read_cb pack_len:%d\n", st2.pack_len);printf("socket_read_cb key:%s\n", msg+sizeof(msg_header));bufferevent_write(bev,msg,sizeof(msg_header)+st2.pack_len);
}void event_cb(struct bufferevent *bev, short event, void *arg)
{if (event & BEV_EVENT_EOF)printf("connection closed\n");else if (event & BEV_EVENT_ERROR)printf("some other error\n");bufferevent_free(bev);
}int tcp_server_init(int port, int listen_num)
{ int errno_save;evutil_socket_t listener;listener = socket(AF_INET, SOCK_STREAM, 0);if( listener == -1 )return -1;//允许多次绑定同一个地址。要用在socket和bind之间evutil_make_listen_socket_reuseable(listener);struct sockaddr_in sin;sin.sin_family = AF_INET;sin.sin_addr.s_addr = 0;sin.sin_port = htons(port);if( bind(listener, (SA*)&sin, sizeof(sin)) < 0 )goto error;if( listen(listener, listen_num) < 0)goto error;//跨平台统一接口,将套接字设置为非阻塞状态evutil_make_socket_nonblocking(listener);return listener;error:evutil_closesocket(listener);return -1;
}
参考:
https://blog.gmem.cc/libevent-study-note
https://blog.csdn.net/weixin_44718794/article/details/107065921
先看效果:先开启服务器后开启服务器
网络编程-libevnet不带缓冲的事件框架相关推荐
- 【Linux网络编程】TCP带外数据
[Linux网络编程]TCP带外数据 [1]TCP 包的部首 TCP带外数据相关概念 紧急字段URG : 当URG=1时,告诉系统此报文段中有紧急数据,应尽快传送. 紧急指针 ...
- 网络编程模型综述 之 成熟的IO框架介绍
ACE "重量级的C++ I/O框架,用面向对象实现了一些I/O策略和其它有用的东西,特别是它的Reactor是用OO方式处理非阻塞I/O,而Proactor是用OO方式处理异步I/O的( ...
- QT入门第七天 网络编程TCP/IP/UDP+Http和JSON解析+qt事件软键盘【CSDN最详细】
网络编程+Http和JSON解析+qt事件软键盘 第一章 QT中的网络编程 [1]涉及到的类 [2]tcp协议的流程 [2.1]服务器的流程 socket-->bind-->listen- ...
- python 网络编程----非阻塞或异步编程
From: http://blog.chinaunix.net/uid-20730371-id-765038.html 非阻塞或异步编程 例如,对于一个聊天室来说,因为有多个连接需要同时被处理,所以很 ...
- 索骥馆-编程语言之《网络编程实用教程(第2版)》扫描版[PDF]
内容介绍: 本书主要介绍基于tcp/ip协议栈的套接字网络编程技术.全书分为10章,第1章介绍网络编程基础,第2章介绍套接字网络编程接口,第3章介绍windows环境的网络编程,第4章介绍mfc编程, ...
- 五分钟学Java:如何学习Java面试必考的网络编程
原创声明 本文作者:黄小斜 转载请务必在文章开头注明出处和作者. 本文思维导图 简介 Java作为一门后端语言,对于网络编程的支持是必不可少的,但是,作为一个经常CRUD的Java工程师,很多时候都不 ...
- Linux网络编程 | 定时事件 :Linux常见定时方法、定时器链表、空闲断开
文章目录 Linux定时方法 定时器链表 空闲断开 Linux定时方法 Linux中为我们提供了三种定时方法,分别是Socket超时选项,SIGALRM信号,I/O复用超时参数.下面一一对其进行介绍. ...
- 网络编程实战之高级篇, 彻底解决面试C10k问题, 高并发服务器, IO多路复用, 同时监视多个IO事件
目录 一.前言 二.IO多路复用的理解 三.IO多路复用的发展 select poll epoll 四.C10K服务端代码 五. 总结 一.前言 网络入门篇,从操作系统的层次推开网络大门 网络入门基 ...
- 【带你入门】java网络编程
网络编程 网络编程对于很多的初学者来说,都是很向往的一种编程技能,但是很多的初学者却因为很长一段时间无法进入网络编程的大门而放弃了对于该部分技术的学习. 在 学习网络编程以前,很多初学者可能觉得网络编 ...
最新文章
- tf_geometric的安装
- awx文件解析_Android so(ELF)文件解析
- 88是python语言的整数类型_Python基础数据类型题
- 【文章】鱼那么信任水, 水却煮了鱼!
- 互联网日报 | 阿里国内消费者已接近10亿;联想布局半导体赛道;我国5G用户超过6千万户...
- 【高清截图】UbuntuKylin 14.04 桌面版安装步骤
- 一个关于先验概率、似然函数与后验概率计算的小例子
- Unix 风雨五十年:老兵远去,新秀崛起!
- html怎么把view变成标签_html单选按钮默认选中怎么做?input标签的单选按钮用法实例...
- fvcore CfgNode
- 智能座舱:汽车雷达的下一个战场
- 2.三种前端跨域的解决方法
- 收藏 | 应急响应的基本流程
- Django登录并使用LDAP认证
- Xcode 设置macos app的适配系统,显示禁止图标
- 国产接口调试工具ApiPost推荐,媲美postman
- ZOJ4062 Plants vs. Zombies 二分
- Spring Data JPA-JPA对象的四种状态
- Gbps Mbps Bps bps的进制转换
- AI的故事:半人马的诞生之路
热门文章
- 天高任鸟飞,在你还苦闷Android出路时,总有人在系统钻研为高级开发做准备,技能提升的重要性不用我说了!
- java选择题《每日一练》
- atto软件测试速度,评测平台介绍及HD Tune、ATTO性能测试
- 重复字符串的处理问题
- WEB 期末项目 小黑帽书屋
- ARM CPU性能优化:FP32 、FP16 和BF16区别
- 动态时间规整算法DTW
- HTML中placeholder用法
- docx_demos(创建文档类Document及属性方法, 创建段落文本类Paragraph及段落格式设置, 创建字体设置类Run及属性等)
- 【jzoj4597】【现世斩】【平衡树】【set】