写了一个简单的例子,把libevent中的bufferevent网络收发服务和protobuf里面的序列反序列结合起来。

protobuf文件message.proto:

message PMessage {required int32 id = 1;optional int32 num = 2;optional string str = 3;
}

生成接口命令:

protoc -I=proto --cpp_out=src proto/message.proto

服务器端 lserver.cc:

#include <netinet/in.h>
#include <sys/socket.h>
#include <unistd.h>#include <stdio.h>
#include <string.h>#include <event.h>
#include <event2/listener.h>
#include <event2/bufferevent.h>
#include <event2/thread.h>#include "message.pb.h"using namespace std;void listener_cb(evconnlistener *listener, evutil_socket_t fd,sockaddr *sock, int socklen, void *arg);void socket_read_cb(bufferevent *bev, void *arg);void socket_event_cb(bufferevent *bev, short events, void *arg);int main(int argc, char **argv) {sockaddr_in sin;memset(&sin, 0, sizeof(sockaddr_in));sin.sin_family = AF_INET;sin.sin_port = htons(8899);event_base *base = event_base_new();evconnlistener *listener= evconnlistener_new_bind(base,listener_cb, base,LEV_OPT_REUSEABLE|LEV_OPT_CLOSE_ON_FREE,10, (sockaddr*)&sin, sizeof(sockaddr_in));event_base_dispatch(base);evconnlistener_free(listener);event_base_free(base);}void listener_cb(evconnlistener *listener, evutil_socket_t fd,sockaddr *sock, int socklen, void *arg) {printf("accept a client %d\n", fd);event_base *base = (event_base *)arg;bufferevent *bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);bufferevent_setcb(bev, socket_read_cb, NULL, socket_event_cb, NULL);bufferevent_enable(bev, EV_READ|EV_PERSIST);}void socket_read_cb(bufferevent *bev, void *arg) {char msg[4096];size_t len = bufferevent_read(bev, msg, sizeof(msg)-1);msg[len] = '\0';PMessage pmsg;pmsg.ParseFromArray((const void*)msg, len);printf("Server read the data:%i, %i, %s\n", pmsg.id(), pmsg.num(), pmsg.str().c_str());pmsg.set_str("I have read your data.");string sendbuf;pmsg.SerializeToString(&sendbuf);bufferevent_write(bev, sendbuf.c_str(), sendbuf.length());}void socket_event_cb(bufferevent *bev, short events, void *arg) {if (events & BEV_EVENT_EOF) {printf("connection close\n");}else if (events & BEV_EVENT_ERROR) {printf("some other error\n");}bufferevent_free(bev);
}

客户端lclient.cc

#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>#include "message.pb.h"using namespace std;void cmd_msg_cb(int fd, short events, void *arg);void server_msg_cb(bufferevent *bev, void *arg);void event_cb(bufferevent *bev, short event, void *arg);static int gid = 1;int main(int argc, char **argv) {if (argc < 3) {printf("please input IP and port\n");return 1;}event_base *base = event_base_new();bufferevent *bev = bufferevent_socket_new(base, -1, BEV_OPT_CLOSE_ON_FREE);event *ev_cmd = event_new(base, STDIN_FILENO,EV_READ|EV_PERSIST,cmd_msg_cb, (void *)bev);event_add(ev_cmd, NULL);sockaddr_in server_addr;memset(&server_addr, 0, sizeof(server_addr));server_addr.sin_family = AF_INET;server_addr.sin_port = htons(atoi(argv[2]));inet_aton(argv[1], &server_addr.sin_addr);bufferevent_socket_connect(bev, (sockaddr*)&server_addr, sizeof(server_addr));bufferevent_setcb(bev, server_msg_cb, NULL, event_cb, (void*)ev_cmd);bufferevent_enable(bev, EV_READ|EV_PERSIST);event_base_dispatch(base);printf("Finish\n");return 0;}void cmd_msg_cb(int fd, short events, void *arg) {char msg[1024];int ret = read(fd, msg, sizeof(msg));if (ret < 0) {perror("read error.\n");exit(1);}// protobuf
        PMessage pmsg;pmsg.set_id(gid++);pmsg.set_num(rand());pmsg.set_str(msg);string sendbuf;pmsg.SerializeToString(&sendbuf);// processing network transferbufferevent *bev = (bufferevent *)arg;bufferevent_write(bev, sendbuf.c_str(), sendbuf.length());
}void server_msg_cb(bufferevent *bev, void *arg) {char msg[1024];size_t len = bufferevent_read(bev, msg, sizeof(msg)-1);msg[len] = '\0';PMessage pmsg;pmsg.ParseFromArray((const void*)msg, len);printf("Recv %d, %d, %s from server.\n", pmsg.id(), pmsg.num(), pmsg.str().c_str());
}void event_cb(bufferevent *bev, short eventid, void *arg) {if (eventid & BEV_EVENT_EOF) {printf("Connection closed.\n");}else if (eventid & BEV_EVENT_ERROR) {printf("Some other error.\n");}else if (eventid & BEV_EVENT_CONNECTED) {printf("Client has successfully connected.\n");return;}bufferevent_free(bev);event *ev = (event *)arg;event_free(ev);
}

服务器端和客户端共用的Makefile:

CXX=/opt/compiler/gcc-4.8.2/bin/g++INCPATH= \/home/work/.jumbo/include/DEP_LDFLAGS= \-L/home/work/.jumbo/lib/DEP_LDLIBS= \-levent \-lprotobuf \-lpthreadTARGET= lserver lclientall : $(TARGET)lserver : lserver.cc message.pb.cc$(CXX) -o $@ $^ -I$(INCPATH) $(DEP_LDFLAGS) $(DEP_LDLIBS)lclient : lclient.cc message.pb.cc$(CXX) -o $@ $^ -I$(INCPATH) $(DEP_LDFLAGS) $(DEP_LDLIBS).PHONY : all cleanclean :rm -rf $(TARGET)

服务器命令及输出:

src]$ ./lserver
accept a client 7
Server read the data:1, 1804289383, aaaaaaaaaaaaaaaaaaaaaaaaaServer read the data:2, 846930886, aaServer read the data:3, 1681692777, bbServer read the data:4, 1714636915, abcdefgServer read the data:5, 1957747793, connection close
accept a client 7
Server read the data:1, 1804289383, 2aaServer read the data:2, 846930886, 2bbServer read the data:3, 1681692777, 111111111111111111111222222222222222222222223333333333333333333333333Server read the data:4, 1714636915, ^C

客户端命令及输出:

src]$ ./lclient localhost 8899
Client has successfully connected.
aaaaaaaaaaaaaaaaaaaaaaaaa
Recv 1, 1804289383, I have read your data. from server.
aa
Recv 2, 846930886, I have read your data. from server.
bb
Recv 3, 1681692777, I have read your data. from server.
abcdefg
Recv 4, 1714636915, I have read your data. from server.Recv 5, 1957747793, I have read your data. from server.
^C
[src]$ ./lclient localhost 8899
Client has successfully connected.
2aa
Recv 1, 1804289383, I have read your data. from server.
2bb
Recv 2, 846930886, I have read your data. from server.
111111111111111111111222222222222222222222223333333333333333333333333
Recv 3, 1681692777, I have read your data. from server.Recv 4, 1714636915, I have read your data. from server.
Connection closed.
Finish

注意:

1. 先后开了两个客户端。客户端退出,不影响服务器端。但是服务器端退出会让客户端一起退出,因为客户端在收到网络error信号处理的最后,会free掉从命令行读数据的监听event,这样eventbase就不会再有event需要监听了,所以会退出。

2. 开始在命令行输入的时候,在char数组中没有添加'\0',传输时会造成如下错误。

[libprotobuf ERROR google/protobuf/wire_format.cc:1053] String field contains invalid UTF-8 data when serializing a protocol buffer. Use the 'bytes' type if you intend to send raw bytes.

根据读入函数返回的长度,设置'\0'即可避免这个错误。

转载于:https://www.cnblogs.com/charlesblc/p/5923738.html

融合libevent和protobuf相关推荐

  1. 智能驾驶功能软件平台设计规范 第二部分:感知融合功能服务接口

    智能驾驶功能软件平台设计规范 第二部分:感知融合功能服务接口 版本:1.0 2020-07-29 发布 1 规范应用范围 本规范规定了智能驾驶功能软件平台中的感知融合功能服务接口. 本规范适用于设计开 ...

  2. 谷歌protobuf(Protocol buffers)的使用

    谷歌protobuf的使用 一.概述 二.安装 三.protobuf中的限定符 四.protobuf支持的数据类型 五.编译 1. 将proto文件编译成 C++ 文件 2. 将编译好的文件与代码一起 ...

  3. 教你成为全栈工程师(Full Stack Developer) 〇-什么是全栈工程师

    作为一个编码12年的工程师老将,讲述整段工程师的往事,顺便把知识都泄露出去,希望读者能少走一些弯路. 这段往事包括:从不会动的静态网页到最流行的网站开发.实现自己的博客网站.在云里雾里的云中搜索.大数 ...

  4. libevent介绍

    libevent是一款事件驱动的网络开发包 由于采用 c 语言开发 体积小巧,跨平台,速度极快. 通常我们在建立服务器的处理模型的时候,主要是下面集中模型; (1)    a new Connecti ...

  5. 使用大数据闪存打造融合数据平台

    随着企业.服务提供商和超大型数据中心从描述性分析向预测性和规范性分析演进,结合了融合运营和分析数据管道的融合数据平台变得日益重要.大数据闪存可让数据处理平台快速访问历史数据和实时数据流,从而以较低成本 ...

  6. pythongoogle.probuf.timestamp_gRPC快速入门(一)——Protobuf简介

    gRPC快速入门(一)--Protobuf简介 一.Protobuf简介 1.Protobuf简介 Protobuf即Protocol Buffers,是Google公司开发的一种跨语言和平台的序列化 ...

  7. libevent源码深度剖析九

    libevent源码深度剖析九 --集成定时器事件 张亮 现在再来详细分析libevent中I/O事件和Timer事件的集成,与Signal相比,Timer事件的集成会直观和简单很多.Libevent ...

  8. 图文分析:如何利用Google的protobuf,来思考、设计、实现自己的RPC框架

    [CSDN 编者按]本文主要分析 Google 的 protobuf 序列化工具的基本原理和使用.利用 protobuf 序列化功能, libevent 网络通信功能,来设计.实现自己的 RPC 远程 ...

  9. Caffe中BN层与CONV层的融合(merge_bn)

    半年前写的博客,今天发现没有发出去,还好本地有md的文档,决定重新发一下 毕竟网上来回抄袭的blog太多了,代码质量也莫得保证 今天需要用pytorch融合下bn层,写个脚本稍后再传到csdn上 原理 ...

最新文章

  1. live555从RTSP服务器读取数据到使用接收到的数据流程分析
  2. AMFPHP快速入门
  3. 您需要了解的有关UI测试的所有信息
  4. 怎样把连续的多个commit整理成1个?
  5. mac android 证书生成工具,MAC系统下,生成安卓证书的命令
  6. python做界面小软件_PySimpleGUI图形界面绘制及办公自动化小软件的制作
  7. 拖得太久了 美运营商ATT取消三星折叠手机Galaxy Fold预购订单
  8. zabbix-agent自定义监控项
  9. 常用的JS与XML结合用法 简单示例
  10. SpringBoot实现前后端数据交互、json数据交互、Controller接收参数的几种常用方式...
  11. Python虚拟环境的搭建
  12. 二维向量vector初始化问题(以统计字符串字母题为例)
  13. 网线连接电脑共享文件传递
  14. 2018年尚硅谷徐靖博老师的分布式电商项目视频
  15. bat运行Java程序
  16. oppo手机linux模式,OPPO工程模式怎么进 OPPO手机指令有哪些
  17. wps和office哪个好用 wps和office兼容吗
  18. 微信企业号开发(2)--建立连接(主动)
  19. 使用handeye_calib_camodocal进行手眼标定
  20. vs2008编译QT开源项目--太阳神三国杀源码分析(二) 客户端添加武将

热门文章

  1. boost::core模块实现交换std的dateorder
  2. Boost:bind绑定的function<>测试程序
  3. Boost:基于Boost的管道pipeline通信
  4. ITK:用内核卷积图像
  5. VTK:网格之FitToHeightMap
  6. VTK:隐式函数之ImplicitDataSet
  7. C语言已排序链表插入新节点保持排序状态(附完整源码)
  8. C语言unit test单元测试类的实现(附完整源码)
  9. OpenGL Fur Rendering毛发渲染的实例
  10. C++Slow Sort慢排序的实现算法(附完整源码)