您的位置:首页 > 科技 > 能源 > 网上卖货平台有哪些_哪里有学网页设计_网站免费建站app_seo网站推广培训

网上卖货平台有哪些_哪里有学网页设计_网站免费建站app_seo网站推广培训

2024/12/23 16:46:40 来源:https://blog.csdn.net/SlanderMC/article/details/143582156  浏览:    关键词:网上卖货平台有哪些_哪里有学网页设计_网站免费建站app_seo网站推广培训
网上卖货平台有哪些_哪里有学网页设计_网站免费建站app_seo网站推广培训

libevent库

开源。精简。跨平台(Windows、Linux、maxos、unix)。专注于网络通信。
特性:
基于“事件”异步通信模型。— 回调。

event

在这里插入图片描述

  1. 创建 event_base (乐高底座)

     struct event_base *event_base_new(void);struct event_base *base = event_base_new();
    
  2. 创建 事件evnet

     常规事件 event	--> event_new(); 带缓冲区的事件(网络)bufferevent --> bufferevent_socket_new();
    
  3. 将事件 添加到 base上

     int event_add(struct event *ev, const struct timeval *tv)
    
  4. 循环监听事件满足

     int event_base_dispatch(struct event_base *base);event_base_dispatch(base);
    
  5. 释放 event_base

     event_base_free(base);
    

创建事件对象

创建事件event:

struct event *ev;

struct event *event_new(struct event_base base,evutil_socket_t fd,short what,event_callback_fn cb; void arg);
将event事件创建,并指定其回调函数void eventcallback(fd,what,void)。

参数:
base: event_base_new()返回值。

fd: 绑定到 event 上的 文件描述符

what:对应的事件(r、w、e)
EV_READ 一次 读事件
EV_WRTIE 一次 写事件
EV_PERSIST 持续触发。 结合 event_base_dispatch 函数使用,生效。

cb:一旦事件满足监听条件,回调的函数。
typedef void (*event_callback_fn)(evutil_socket_t fd, short, void *)
arg: 回调的函数的参数。

返回值:
成功创建的 event

事件event操作

添加事件到 event_base

int event_add(struct event *ev, const struct timeval *tv);
ev: event_new() 的返回值。
tv:NULL

销毁事件

int event_free(struct event *ev);

ev: event_new() 的返回值。

使用fifo的读写

读管道

1.#include <stdio.h>  
2.#include <unistd.h>  
3.#include <stdlib.h>  
4.#include <sys/types.h>  
5.#include <sys/stat.h>  
6.#include <string.h>  
7.#include <fcntl.h>  
8.#include <event2/event.h>  
9.  
10.// 对操作处理函数  
11.void read_cb(evutil_socket_t fd, short what, void *arg)  
12.{  
13.    // 读管道  
14.    char buf[1024] = {0};  
15.      
16.    int len = read(fd, buf, sizeof(buf));  
17.      
18.    printf("read event: %s \n", what & EV_READ ? "Yes" : "No");  
19.    printf("data len = %d, buf = %s\n", len, buf);  
20.      
21.    sleep(1);  
22.}  
23.  
24.  
25.// 读管道  
26.int main(int argc, const char* argv[])  
27.{  
28.    unlink("myfifo");  
29.  
30.    //创建有名管道  
31.    mkfifo("myfifo", 0664);  
32.  
33.    // open file  
34.    //int fd = open("myfifo", O_RDONLY | O_NONBLOCK);  
35.    int fd = open("myfifo", O_RDONLY);  
36.    if(fd == -1)  
37.    {  
38.        perror("open error");  
39.        exit(1);  
40.    }  
41.  
42.    // 创建个event_base  
43.    struct event_base* base = NULL;  
44.    base = event_base_new();  
45.  46.// 创建事件  
47.    struct event* ev = NULL;  
48.    ev = event_new(base, fd, EV_READ | EV_PERSIST, read_cb, NULL);  
49.  
50.    // 添加事件  
51.    event_add(ev, NULL);  
52.  
53.    // 事件循环  
54.    event_base_dispatch(base);  // while(1) { epoll();}  
55.  
56.    // 释放资源  
57.    event_free(ev);  
58.    event_base_free(base);  
59.    close(fd);  
60.      
61.    return 0;  
62.}  

写管道

1.#include <stdio.h>  
2.#include <unistd.h>  
3.#include <stdlib.h>  
4.#include <sys/types.h>  
5.#include <sys/stat.h>  
6.#include <string.h>  
7.#include <fcntl.h>  
8.#include <event2/event.h>  
9.  
10.// 对操作处理函数  
11.void write_cb(evutil_socket_t fd, short what, void *arg)  
12.{  
13.    // write管道  
14.    char buf[1024] = {0};  
15.      
16.    static int num = 0;  
17.    sprintf(buf, "hello,world-%d\n", num++);  
18.    write(fd, buf, strlen(buf)+1);  
19.      
20.    sleep(1);  
21.}  
22.  
23.  
24.// 写管道  
25.int main(int argc, const char* argv[])  
26.{  27.// open file  
28.    //int fd = open("myfifo", O_WRONLY | O_NONBLOCK);  
29.    int fd = open("myfifo", O_WRONLY);  
30.    if(fd == -1)  
31.    {  
32.        perror("open error");  
33.        exit(1);  
34.    }  
35.  
36.    // 写管道  
37.    struct event_base* base = NULL;  
38.    base = event_base_new();  
39.  
40.    // 创建事件  
41.    struct event* ev = NULL;  
42.    // 检测的写缓冲区是否有空间写  
43.    //ev = event_new(base, fd, EV_WRITE , write_cb, NULL);  
44.    ev = event_new(base, fd, EV_WRITE | EV_PERSIST, write_cb, NULL);  
45.  
46.    // 添加事件  
47.    event_add(ev, NULL);  
48.  
49.    // 事件循环  
50.    event_base_dispatch(base);  
51.  
52.    // 释放资源  
53.    event_free(ev);  
54.    event_base_free(base);  
55.    close(fd);  
56.      
57.    return 0;  
58.}  

未决和非未决

非未决: 没有资格被处理
未决: 有资格被处理,但尚未被处理

event_new --> event —> 非未决 --> event_add --> 未决 --> dispatch() && 监听事件被触发 --> 激活态

–> 执行回调函数 --> 处理态 --> 非未决 event_add && EV_PERSIST --> 未决 --> event_del --> 非未决
在这里插入图片描述

bufferevent特性

在这里插入图片描述#include <event2/bufferevent.h>

原理:
bufferevent有两个缓冲区:也是队列实现,数据只能读一次,先进先出(管道)
读:有数据–>读回函数被调用–>使用bufferevent_read()–>读数据
写:使用bufferevent_write()–>向写缓冲区中写数据–>写完后回调函数被调用(通知写数据成功了,比较鸡肋)

bufferevent的创建和释放

  1. 创建:
    函数原型:
    struct bufferevent *bufferevent_socket_new(struct event_base *base, evutil_socket_t fd, enum bufferevent_options options);
    作用:
    创建bufferevent对象,并加入到base中。
    使用:
    struct bufferevent *bev = bufferevent_socket_new(base,fd,BEV_OPT_CLOSE_ON_FREE)
    参数:
    base:event_base(底座)
    fd:文件描述符,此处有歧义:应该传入的是与客户端连接的套接字描述符 cfd,而不是用于监听的套接字描述符 lfd。
    options:BEV_OPT_CLOSE_ON_FREE()
    返回:成功创建的 bufferevent事件对象
  2. 释放:
    void bufferevent_socket_free(struct bufferevent *bev);
    参数:
    bufferevent事件对象

给bufferevent读写缓冲区设置回调

  1. 设置回调:
    void bufferevent_setcb(struct bufferevent * bufev,
    bufferevent_data_cb readcb,
    bufferevent_data_cb writecb,
    bufferevent_event_cb eventcb,
    void *cbarg );
    参数:
    bufev:bufferevent_socket_new的返回值(bufferevent事件对象)
    readcb:设置buffeverent读缓冲的对应回调 read_cb { bufferevent_read() 读数据 }
    writecb:设置buffeverent写缓冲的对应回调 write_cb {} -->给调用者发送写成功的通知,可传NULL
    eventcb:设置事件回调,也可传NULL
    cbarg:上述回调函数的参数

2.readcb原型
read 回调函数类型:
typedef void (*bufferevent_data_cb)(struct bufferevent bev, voidctx);
使用:
void read_cb(struct bufferevent *bev, void *cbarg )
{

bufferevent_read(); — read();
bufferevent_write(); —write();
//这两个函数用于替代read和write
}

bufferevent_read()函数的原型:

	size_t bufferevent_read(struct bufferevent *bev, void *buf, size_t bufsize);

bufferevent_write 回调函数类型:

	int bufferevent_write(struct bufferevent *bev, const void *buf,  size_t size);
  1. write_cb:
    int bufferevent_write(struct bufferevent *bufev, const void *data, size_t size);

4.event_cb:
在这里插入图片描述

禁用、启用缓冲区

默认bufferevent的读缓冲是关闭的,需要使用bufferevent_get_enabled来开启。
在这里插入图片描述原型:
void bufferevent_enable(struct bufferevent *bufev, short events); 启动
events: EV_READ、EV_WRITE、EV_READ|EV_WRITE
用法:
bufferevent_enable(evev, EV_READ); – 开启读缓冲

通信相关函数

客户端:
int bufferevent_socket_connect(struct bufferevent *bev, struct sockaddr *address, int addrlen);
参数:
bev: bufferevent 事件对象(封装了fd)
address、len:等同于 connect()的参2和参3-------服务器的地址结构

服务器:
加头文件:#include <event2/listener.h>

struct evconnlistener * listener = evconnlistener_new_bind()
struct evconnlistener *evconnlistener_new_bind
(
struct event_base *base,
evconnlistener_cb cb,
void *ptr,
unsigned flags,
int backlog,
const struct sockaddr *sa,
int socklen
);
这一个函数可以完成:socket()、bind()、listen()、accept() 这四个函数的作用

参数:
base:event_base;
cb:回调函数–>一旦被回调,说明客户端与服务器请求建立连接;
ptr:回调函数的参数,将base传进去,在回调函数中创建bufferevent时要用
flags:LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE(端口复用)
backlog:listen()的参数二,即最大连接客户端数量,传-1表示最大值
sa:服务器自己的地址结构体
socklen:服务器自己地址结构体的大小
返回值:成功创建的监听器listener

释放:

void evconnlistener_free(struct evconnlistener *lev);

通信流程分析

服务器
在这里插入图片描述客户端
在这里插入图片描述

实现代码

服务器

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <event2/event.h>
#include <event2/listener.h>
#include <event2/bufferevent.h>// bev对象的读写回调
void read_cb(struct bufferevent *bev, void *arg)
{char buf[1024];// 从客户端中读bufferevent_read(bev, buf, sizeof(buf));printf("client say:%s\n", buf);char *p = "我是服务器,已经成功收到你发送的数据";// 写数据给客户端bufferevent_write(bev, p, strlen(p) + 1);sleep(1);
}
void write_cb(struct bufferevent *bev, void *arg)
{printf("I'm 服务器,成功写数据给客户端了,写缓冲区回调函数被调用...\n");
}// listener监听器的回调函数
void listener_cb(struct evconnlistener *listener,evutil_socket_t fd,struct sockaddr *addr,int len, void *ptr)
{printf("connect new client");// 接收监听器传进来的basestruct event_base *base = (struct event_base *)ptr;// 创建bev对象,用于监听客户端的读写事件struct bufferevent *bev;bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);// 设置bev对象的读写回调bufferevent_setcb(bev, read_cb, write_cb, NULL, NULL);// 设置读的权限bufferevent_enable(bev, EV_READ);
}int main()
{// 地址结构体struct sockaddr_in serve_addr;serve_addr.sin_family = AF_INET;serve_addr.sin_port = htons(9527);serve_addr.sin_addr.s_addr = htonl(INADDR_ANY);// 1. 创建底座struct event_base *base = event_base_new();// 2. 创建listener监听对象,(监听是否有客户端连接)struct evconnlistener *listener;listener = evconnlistener_new_bind(base, listener_cb, base,LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE,-1, (struct sockaddr *)&serve_addr, sizeof(serve_addr));// 3. 启动循环监听event_base_dispatch(base);// 4. 释放event_base_free(base);         // 底座evconnlistener_free(listener); // 监听器return 0;
}

客户端

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <event2/event.h>
#include <event2/listener.h>
#include <event2/bufferevent.h>
#include <arpa/inet.h>// 读写回调
void read_cb(struct bufferevent *bev, void *arg)
{char buf[1024] = {0};bufferevent_read(bev, buf, sizeof(buf));printf("服务器 say:%s\n", buf);bufferevent_write(bev, buf, strlen(buf) + 1);sleep(1);
}void write_cb(struct bufferevent *bev, void *arg)
{printf("----------我是客户端的写回调函数,没卵用\n");
}void event_cb(struct bufferevent *bev, short events, void *arg)
{if (events & BEV_EVENT_EOF){printf("connection closed\n");}else if (events & BEV_EVENT_ERROR){printf("some other error\n");}else if (events & BEV_EVENT_CONNECTED){printf("已经连接服务器...\\(^o^)/...\n");return;}//  释放资源  bufferevent_free(bev);
}int main()
{// 1. 创建base底座struct event_base *base = event_base_new();// 描述符int fd = socket(AF_INET, SOCK_STREAM, 0);// 地址结构struct sockaddr_in client_addr;memset(&client_addr, 0, sizeof(client_addr));client_addr.sin_family = AF_INET;client_addr.sin_port = htons(9527);inet_pton(AF_INET, "127.0.0.1", &client_addr.sin_addr.s_addr);// 2. 创建bev对象struct bufferevent *bev = NULL;bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);// 3. 连接服务器bufferevent_socket_connect(bev, (struct sockaddr *)&client_addr, sizeof(client_addr));// 4. 设置回调bufferevent_setcb(bev, read_cb, write_cb, event_cb, NULL);// 设置读回调生效bufferevent_enable(bev, EV_READ);// 5. 启动循环监听event_base_dispatch(base);// 6. 销毁event_base_free(base);bufferevent_free(bev);return 0;
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com