0
点赞
收藏
分享

微信扫一扫

多维时序 | MATLAB实现SSA-CNN-GRU-SAM-Attention麻雀算法优化卷积网络结合门控循环单元网络融合空间注意力机制多变量时间序列预测

仲秋花似锦 2024-01-01 阅读 66

目录

目标

  1. 明白网络模块要处理那些事情
  2. reactor 是怎么处理这些事情的
  3. reactor 如何封装的
  4. 网络模块与业务逻辑的关系
  5. 如何优化 reactor

网络编程关注的问题

连接的建立

int clientfd = accept(listenfd, addr, sz);
// 举例为非阻塞io,阻塞io成功直接返回0;
int connectfd = socket(AF_INET, SOCK_STREAM, 0);
int ret = connect(connectfd, (struct sockaddr
*)&addr, sizeof(addr));
// ret == -1 && errno == EINPROGRESS 正在建立连接
// ret == -1 && errno = EISCONN 连接建立成功

连接的断开

// 主动关闭
close(fd);
shutdown(fd, SHUT_RDWR);
// 主动关闭本地读端,对端写段关闭
shutdown(fd, SHUT_RD);
// 主动关闭本地写端,对端读段关闭
shutdown(fd, SHUT_WR);

// 被动:读端关闭
// 有的网络编程需要支持半关闭状态
int n = read(fd, buf, sz);
if (n == 0) {
    close_read(fd);
    // write()
    // close(fd);
}

// 被动:写端关闭
int n = write(fd, buf, sz);
if (n == -1 && errno == EPIPE) {
    close_write(fd);
    // close(fd);
}

消息的到达

int n = read(fd, buf, sz);
if (n < 0) { // n == -1
    if (errno == EINTR || errno == EWOULDBLOCK)
        break;
    close(fd);
} else if (n == 0) {
    close(fd);
} else {
    // 处理 buf
}

消息发送完毕

int n = write(fd, buf, dz);
if (n == -1) {
    if (errno == EINTR || errno == EWOULDBLOCK) {
        return;
   }
    close(fd);
}

网络 IO 职责

检测 IO

检测 io剖析

  io 函数和系统调用中都有用到 检测 io。主要功能就是检测 io 是否就绪,如果对应到 socket 网络通信来说每个函数检测的部分如下:

acccept();//检测全连接队列是否有数据:
		  //第 1 次握手:将数据放到半连接队列
		  //第 3 次握手:将数据放入全连接队列
		  
connect();//检测是否收到 ACK,收到 ACK 就代表 IO 就绪,连接成功
		  //第 2 次握手成功,就表示 client 连接成功
		  
read = 0; //检测 buf 是否含有 EOF 标记
		  //关闭连接时,会往对应的缓冲区写入 EOF,读到 EOF 就会返回 0

write //就是把数据写到 send_buf 缓冲区中,至于数据什么时候写,以什么形式写,何时到达对端,都是根绝协议栈来决定的

操作 IO

阻塞IO 和 非阻塞IO

// 默认情况下,fd 是阻塞的,设置非阻塞的方法如下;
int flag = fcntl(fd, F_GETFL, 0);
fcntl(fd, F_SETFL, flag | O_NONBLOCK);

详细分析可以看I/O详解与五种网络I/O模型

IO 多路复用

详细分析可以看I/O详解与五种网络I/O模型

epoll

结构以及接口

struct eventpoll {
    // ...
    struct rb_root rbr; // 管理 epoll 监听的事件
    struct list_head rdllist; // 保存着 epoll_wait
返回满⾜条件的事件
    // ...
};
struct epitem {
    // ...
    struct rb_node rbn; // 红⿊树节点
    struct list_head rdllist; // 双向链表节点
    struct epoll_filefd ffd; // 事件句柄信息
    struct eventpoll *ep; // 指向所属的eventpoll对struct epoll_event event; // 注册的事件类型
    // ...
};
struct epoll_event {
    __uint32_t events; // epollin epollout
epollel(边缘触发)
    epoll_data_t data; // 保存 关联数据
};

typedef union epoll_data {
   void *ptr;
   int fd;
   uint32_t u32;
   uint64_t u64;
}epoll_data_t;

int epoll_create(int size);

/**
op:
EPOLL_CTL_ADD
EPOLL_CTL_MOD
EPOLL_CTL_DEL

event.events:
EPOLLIN 注册读事件
EPOLLOUT 注册写事件
EPOLLET 注册边缘触发模式,默认是水平触发
*/
int epoll_ctl(int epfd, int op, int fd, struct epoll_event* event);

/**
events[i].events:
EPOLLIN 触发读事件
EPOLLOUT 触发写事件
EPOLLERR 连接发生错误
EPOLLRDHUP 连接读端关闭
EPOLLHUP 连接双端关闭
*/
int epoll_wait(int epfd, struct epoll_event*
events, int maxevents, int timeout);

reactor编程

连接建立

// 一、处理客户端的连接
// 1. 注册监听 listenfd 的读事件
struct epoll_event ev;
ev.events |= EPOLLIN;
epoll_ctl(efd, EPOLL_CTL_ADD, listenfd, &ev);
// 2. 当触发 listenfd 的读事件,调用 accept 接收新的连int clientfd = accept(listenfd, addr, sz);
struct epoll_event ev;
ev.events |= EPOLLIN;
epoll_ctl(efd, EPOLL_CTL_ADD, clientfd, &ev);
// 二、处理连接第三方服务
// 1. 创建 socket 建立连接
int connectfd = socket(AF_INET, SOCK_STREAM, 0);
connect(connectfd, (struct sockaddr *)&addr,
sizeof(addr));
// 2. 注册监听 connectfd 的写事件
struct epoll_event ev;
ev.events |= EPOLLOUT;
epoll_ctl(efd, EPOLL_CTL_ADD, connectfd, &ev);
// 3. 当 connectfd 写事件被触发,连接建立成功
if (status == e_connecting && e->events &
EPOLLOUT) {
    status == e_connected;
    // 这里需要把写事件关闭
    epoll_ctl(epfd, EPOLL_CTL_DEL, connectfd,
NULL);
}

连接断开

if (e->events & EPOLLRDHUP) {
    // 读端关闭
    close_read(fd);
    close(fd);
}
if (e->events & EPOLLHUP) {
    // 读写端都关闭
    close(fd);
}

数据到达

// reactor 要用非阻塞io  
// select
if (e->events & EPOLLIN) {
    while (1) {
        int n = read(fd, buf, sz);
        if (n < 0) {
            if (errno == EINTR)
                continue;
            if (errno == EWOULDBLOCK)
                break;
            close(fd);
       } else if (n == 0) {
            close_read(fd);
            // close(fd);
       }
        // 业务逻辑了
   }
}

数据发送完毕

int n = write(fd, buf, dz);
if (n == -1) {
    if (errno == EINTR)
        continue;
    if (errno == EWOULDBLOCK) {
        struct epoll_event ev;
        ev.events = EPOLLOUT;
        epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev);
        return;
 }
    close(fd);
}
// ...
if (e->events & EPOLLOUT) {
    int n = write(fd, buf, sz);
    //...
    if (n == sz) {
        epoll_ctl(epfd, EPOLL_CTL_DEL, fd, NULL);
   }
}

reactor 应用:后续补充源码解析

单 reacrtor

在这里插入图片描述

多 reactor(one eventloop per thread)

多线程

在这里插入图片描述

多进程

在这里插入图片描述

举报

相关推荐

0 条评论