网络编程-libevnet不带缓冲的事件框架
網(wǎng)絡(luò)編程-libevnet不帶緩沖的事件框架
1.1工作流程
圖1 工作流程
常用的API:
| 分類 | API | 含義 |
| ? 事件 框架 | struct event_base* event_base_new(void); | 創(chuàng)建事件框架 |
| 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); | 創(chuàng)建新事件: EV_READ:讀 EV_WRITE:寫 EV_SIGNAL:信號量EV_PERSIST:持續(xù)觸發(fā)EV_ET://邊沿模式 |
| void event_free(struct event *event); | 釋放事件 | |
| int event_add( struct event *ev, const struct timeval *tv); | 設(shè)置未決事件 | |
| int event_del(struct event *ev); | 設(shè)置已決事件 | |
| event_base_dispatch(struct event_base* base) | 開始循環(huán) | |
| int event_base_loopexit( struct event_base *base, ??? const struct timeval *tv); | 延遲終止循環(huán)(需等待本次事件完成) | |
| int event_base_loopbreak(struct event_base *base); | 立即終止循環(huán) |
?先看效果:先開啟服務(wù)器后開啟服務(wù)器
這個例子簡單的連接,取代傳統(tǒng)的socket的編寫網(wǎng)絡(luò)編程,還有就是采用多路IO復(fù)用的方式來實現(xiàn)并發(fā),此程序沒有進行優(yōu)化,比如
- 當(dāng)首先啟動客戶端程序的時候,將發(fā)生崩潰
- 當(dāng)停止連接的時候,殺掉服務(wù)端,客戶端將瘋狂輸出
- 沒有使用的其他的事件服務(wù)來優(yōu)化代碼,比如定時器,信號量等,這個主要在帶緩存的事件服務(wù)框架里
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));//兩個參數(shù)依次是服務(wù)器端的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();// 創(chuàng)建事件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 服務(wù)器
#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;//跨平臺統(tǒng)一接口,將套接字設(shè)置為非阻塞狀態(tài)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?
先看效果:先開啟服務(wù)器后開啟服務(wù)器
?
總結(jié)
以上是生活随笔為你收集整理的网络编程-libevnet不带缓冲的事件框架的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 电信和互联网用户个人信息保护规定_201
- 下一篇: Vue项目使用拦截器和JWT验证 完整案