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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

网络编程-libevnet不带缓冲的事件框架

發(fā)布時間:2023/12/8 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 网络编程-libevnet不带缓冲的事件框架 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

網(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)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。