日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

融合libevent和protobuf

發布時間:2024/9/21 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 融合libevent和protobuf 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

寫了一個簡單的例子,把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的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。