LINUX 精通 3.2

  1. main里怎么实现

    accept_cb 里的regist部分抽出来

    // regist拉出来
    int event_register(int fd, int event) {if (fd < 0) return -1;conn_list[fd].fd = fd;conn_list[fd].r_action.recv_callback = recv_cb;conn_list[fd].send_callback = send_cb;memset(conn_list[fd].rbuffer, 0, BUFFER_LENGTH);conn_list[fd].rlength = 0;memset(conn_list[fd].wbuffer, 0, BUFFER_LENGTH);conn_list[fd].wlength = 0;set_event(fd, event);
    }// listenfd(sockfd) --> EPOLLIN --> accept_cb
    int accept_cb(int fd) {struct sockaddr_in  clientaddr;socklen_t len = sizeof(clientaddr);int clientfd = accept(fd, (struct sockaddr*)&clientaddr, &len);printf("accept finshed: %d\n", clientfd);/* --------regist--------------conn_list[clientfd].fd = clientfd;conn_list[clientfd].r_action.recv_callback = recv_cb;conn_list[clientfd].send_callback = send_cb;memset(conn_list[clientfd].rbuffer, 0, BUFFER_LENGTH);conn_list[clientfd].rlength = 0;memset(conn_list[clientfd].wbuffer, 0, BUFFER_LENGTH);conn_list[clientfd].wlength = 0;set_event(clientfd, EPOLLIN);--------regist--------------*/event_register(fd, EPOLLIN);return 0;
    }
    

    main里

    
    int main(){unsigned short port = 2000;int sockfd = init_server(port);epfd = epoll_create(1);set_event(sockfd, EPOLLIN);while (1) { // mainloopstruct epoll_event events[1024] = {0};int nready = epoll_wait(epfd, events, 1024, -1);int i = 0;for (i = 0;i < nready;i ++) {int connfd = events[i].data.fd;
    #if 0
    //读写二选一if (events[i].events & EPOLLIN) {conn_list[connfd].r_action.recv_callback(connfd);} else if (events[i].events & EPOLLOUT) {conn_list[connfd].send_callback(connfd);}#else 
    // 读写共存if (events[i].events & EPOLLIN) {conn_list[connfd].r_action.recv_callback(connfd);} if (events[i].events & EPOLLOUT) {conn_list[connfd].send_callback(connfd);}
    #endif}}}
    

    再改进一下set_event的flag 标志add 还是mod

    #include <errno.h>
    #include <stdio.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <string.h>
    #include <pthread.h>
    #include <unistd.h>
    #include <poll.h>
    #include <sys/epoll.h>
    #include <errno.h>
    #include <sys/time.h>#define BUFFER_LENGTH 1024
    typedef int (*RCALLBACK)(int fd); //用于定义一个函数指针类型RCALLBACK。它表示一个接受一个int类型参数fd并返回int类型的函数指针#define CONNECTION_SIZE			1048576 // 1024 * 1024int accept_cb(int fd);
    int recv_cb(int fd);
    int send_cb(int fd);// global variable
    // 抄epoll里构建事件, 把io加入epoll里 不一样封装到set_event里
    // int epfd = epoll_create(1); //不可以这样写,在里面改值
    int epfd = 0;struct conn{int fd; //io是fdchar rbuffer[BUFFER_LENGTH];int rlength;char wbuffer[BUFFER_LENGTH];int wlength;RCALLBACK send_callback;// epollin事件对应callback要么accept或者recv/*这段代码定义了一个联合体(union)r_action,它包含两个成员:accept_callback和recv_callback,它们都是RCALLBACK类型的函数指针。在使用union时,各成员共享同一块内存空间,只能同时使用其中的一个成员。不同成员可以存储不同类型的数据,但在任意给定时间点上只能使用一个成员。该联合体的目的可能是为了提供某种灵活性,在特定情况下可以选择调用accept_callback或recv_callback函数来处理相应的操作。*/union{RCALLBACK accept_callback;RCALLBACK recv_callback;}r_action;};struct conn conn_list[CONNECTION_SIZE] = {0};
    // fdint init_server(unsigned short port){// 创建抄network里// 创建socketint sockfd = socket(AF_INET, SOCK_STREAM, 0);// 绑定本地端口struct sockaddr_in servaddr;servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htons(INADDR_ANY); //绑网卡地址 默认0.0.0.0 绑本地地址;htons转成网络字节序 servaddr.sin_port = htons(port); //改这里 0-1023系统默认 大于1024都能用if(-1 == bind(sockfd, (struct sockaddr*)&servaddr, sizeof(struct sockaddr))){printf("bind failed: %s\n", strerror(errno));}listen(sockfd, 10);printf("listen finished: %d\n", sockfd);return sockfd;
    }int set_event(int fd, int event, int flag){if(flag){struct epoll_event ev; //构建事件,只用来add和delete,control里没用ev.events = event;  //改这里不用epoll,reactor用eventev.data.fd = fd;epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev); }else{struct epoll_event ev; //构建事件,只用来add和delete,control里没用ev.events = event;  //改这里不用epoll,reactor用eventev.data.fd = fd;epoll_ctl(epfd, EPOLL_CTL_MOD, fd, &ev); }
    }// regist拉出来
    int event_register(int fd, int event) {if (fd < 0) return -1;conn_list[fd].fd = fd;conn_list[fd].r_action.recv_callback = recv_cb;conn_list[fd].send_callback = send_cb;memset(conn_list[fd].rbuffer, 0, BUFFER_LENGTH);conn_list[fd].rlength = 0;memset(conn_list[fd].wbuffer, 0, BUFFER_LENGTH);conn_list[fd].wlength = 0;set_event(fd, event, 1);
    }// listenfd(sockfd) --> EPOLLIN --> accept_cb
    int accept_cb(int fd) {struct sockaddr_in  clientaddr;socklen_t len = sizeof(clientaddr);int clientfd = accept(fd, (struct sockaddr*)&clientaddr, &len);printf("accept finshed: %d\n", clientfd);/* --------regist--------------conn_list[clientfd].fd = clientfd;conn_list[clientfd].r_action.recv_callback = recv_cb;conn_list[clientfd].send_callback = send_cb;memset(conn_list[clientfd].rbuffer, 0, BUFFER_LENGTH);conn_list[clientfd].rlength = 0;memset(conn_list[clientfd].wbuffer, 0, BUFFER_LENGTH);conn_list[clientfd].wlength = 0;set_event(clientfd, EPOLLIN);--------regist--------------*/event_register(fd, EPOLLIN);return 0;
    }int recv_cb(int fd) {int count = recv(fd, conn_list[fd].rbuffer, BUFFER_LENGTH, 0);if (count == 0) { // disconnectprintf("client disconnect: %d\n", fd);close(fd);epoll_ctl(epfd, EPOLL_CTL_DEL, fd, NULL); // unfinishedreturn 0;} printf("RECV: %s\n", conn_list[fd].rbuffer);set_event(fd, EPOLLOUT, 0);return count;
    }int send_cb(int fd) {int count = send(fd, conn_list[fd].wbuffer, count, 0);set_event(fd, EPOLLIN, 0);return count;
    }int main(){unsigned short port = 2000;int sockfd = init_server(port);epfd = epoll_create(1);set_event(sockfd, EPOLLIN, 1);while (1) { // mainloopstruct epoll_event events[1024] = {0};int nready = epoll_wait(epfd, events, 1024, -1);int i = 0;for (i = 0;i < nready;i ++) {int connfd = events[i].data.fd;
    #if 0
    //读写二选一if (events[i].events & EPOLLIN) {conn_list[connfd].r_action.recv_callback(connfd);} else if (events[i].events & EPOLLOUT) {conn_list[connfd].send_callback(connfd);}#else 
    // 读写共存if (events[i].events & EPOLLIN) {conn_list[connfd].r_action.recv_callback(connfd);} if (events[i].events & EPOLLOUT) {conn_list[connfd].send_callback(connfd);}
    #endif}}}
    

    ​ 然后编译

    gcc -o reactor reactor.c
    ./reactor
    
  2. 调试

    1. 打开网络调试助手!——tcp client 改port addr
    2. 一直连接报segmentation fault
  3. 总结

    1. fd:对于client recv; 对于server是accept
    2. epoll与reactor区别
      1. reactor:读recv写send分开;每个io封装独立
      2. epoll:不能拿连续收存储

百万并发

没装3个client

看了一遍, reactor老是报错segmentation fault

这部分 跳了,后面再看吧,现在也没看懂,乱七八糟的

遇到问题不要慌,小问题

  1. too many open files:ulimit -n 1048576
  2. 分配ip不够

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/28939.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【吉林大学Java程序设计】第8章:IO流

第8章&#xff1a;IO流 1.流与相关类1.1 流的概念1.2 File类1.3 字节流及其方法1.4 字符流及其方法1.5 其他IO流&#xff08;1&#xff09;节点流&#xff08;2&#xff09;处理流&#xff08;过滤流&#xff09;&#xff08;3&#xff09;文件流基于字节的文件流基于节符的文件…

Shell脚本(.sh文件)如何执行完毕之后不自动关闭?

Shell脚本异常傲娇&#xff0c;出错后、执行完根本不给你机会让你查看报错信息、输出信息&#xff0c;直接闪退。 废话不多说&#xff0c;调教方法如下&#xff0c;直接在Shell脚本末尾加上如下代码&#xff1a; 1、实现方式一 1.1 使用read命令达到类似bat中的pause命令效果…

深度解析响应式异步编程模型

上一篇文章中我们聊了一下线程池,基于线程池的多线程编程是我们在高并发场景下提升系统处理效率的有效手段,但却不是唯一的。今天我们来看一下另一种异步开发的常用手段-响应式编程模型 传统多线程模型的缺陷 多线程模型是目前应用最为广泛的并发编程手段,但凡遇到什么性能…

语义分割——mmsegmentation框架使用

目录 1.mmsegmentation简介 2.mmsegmentation安装 3.mmsegmentation使用&#xff08;代码结构介绍&#xff09; 4.mmsegmentation使用实战&#xff08;deeplab v3为例&#xff09; 4.1配置 4.2训练&#xff1a; 4.3预测&#xff1a; 1.mmsegmentation简介 mmsegmentatio…

LogicFlow 学习笔记——11. 对齐线 和 键盘快捷键

对齐线 Snapline 对齐线能够在节点移动过程中&#xff0c;将移动节点的位置与画布中其他节点位置进行对比&#xff0c;辅助位置调整。位置对比有如下两个方面。 节点中心位置节点的边框 对齐线使用 普通编辑模式下&#xff0c;默认开启对齐线&#xff0c;也可通过配置进行关…

自己想要公开自己的学习方法,但是自己很害怕自己的学习方法是一个错误的,因为对于自己而言,专升本的机会只有一次

分享自己的学习方法可能需要一定的勇气&#xff0c;特别是当你担心可能会受到批评或是不被理解时。以下是一些建议&#xff0c;可以帮助你克服这种恐惧&#xff1a;&#xff08;kimi编辑器自己对于这些内容的基础批注&#xff09; 自我肯定&#xff1a;首先&#xff0c;认识到你…

安裝了windows,Ubuntu双系統,windows系統时间不对的修正方法

当你在电脑上安装双系统(如 Windows 和 Ubuntu)时,系统时间不同步的问题通常是由于这两个操作系统处理系统时间的方式不同而引起的。Windows 默认使用本地时间(Local Time),而 Ubuntu 和其他基于 Linux 的系统通常使用协调世界时(UTC)。 为了解决这个问题,可以选择让…

小程序开发的费用简介篇

小程序的价格跟很多因素有关系&#xff0c;比如你想要的复杂度、功能多不多等等 今天我就来具体说说开发一款APP&#xff0f;小程序到底需要多少 ❶功能复杂度&#xff1a;功能越多越复杂&#xff0c;开发时间和费用就越高&#xff0c;费用就会高 ❷设计要求&#xff1a;高级的…

RAG系列之:深入浅出 Embedding

RAG系列之&#xff1a;深入浅出 Embedding 什么是文本向量化&#xff1f; 文本向量化就是将文本数据转成数字数据&#xff0c;例如&#xff1a;将文本 It was the best of times, it was the worst of times. 转成 [0, 1, 0, 2, 2, 2, 2, 2, 0, 1]。 为什么要进行文本向量化…

深入Linux Core文件生成与自定义命名规则

Linux 作为广泛使用的运行平台&#xff0c;在程序运行崩溃时能及时记录 错误信息&#xff0c;是很方便的查询问题的方式&#xff0c;这里对怎么使用 Linux下的 错误信息记录 core文件&#xff0c;进行总结介绍。 引言 在Linux系统开发中&#xff0c;当程序发生崩溃时&#xf…

FinalShell 连接虚拟机超时,主机ping不通虚拟机,解决

出现问题&#xff1a; 连接主机...java.net.ConnectException: Connection timed out: connect 在排查错误时发现&#xff1a; 虚拟机内能互相ping通&#xff0c;虚拟机能ping通主机 但是主机的cmd命令ping不通虚拟机 问题原因&#xff1a; 虚拟机内能互相ping通&#xff0…

shop APP UI

APP和微信小程序不一样&#xff0c; APP的客户端需要两个(一个安卓&#xff0c;一个苹果IOS); APP的服务端需要&#xff08;管理端后台&#xff0c;接口&#xff09;&#xff1b;

CSS 列表样式(ul)全面解析

CSS 列表样式是前端开发中常用的一种技术&#xff0c;用于定义无序列表&#xff08;ul&#xff09;的外观和行为。无序列表在网页布局和内容展示中扮演着重要角色&#xff0c;从导航菜单到内容清单&#xff0c;无所不在。通过CSS可以对无序列表的各个方面进行自定义&#xff0c…

【Docker】解决访问难题:搭建私有的Docker镜像代理

什么是Nexus 3 Nexus 3是由Sonatype公司开发的一款强大的包管理和仓库服务工具&#xff0c;它广泛应用于自动化的构建系统和持续集成/持续部署(CI/CD)流程中。Nexus 3支持多种包格式&#xff0c;包括但不限于Maven、npm、Docker、NuGet等&#xff0c;能够为软件开发中的依赖管…

vivado PIN

描述 引脚是基元或层次单元上的逻辑连接点。引脚允许 要抽象掉单元格的内容&#xff0c;并简化逻辑以便于使用。引脚可以 是标量的&#xff0c;包含单个连接&#xff0c;或者可以定义为对多个进行分组的总线引脚 信号在一起。 相关对象 引脚连接到一个单元&#xff0c;并且可以…

tyflow线相关教程二

线条生长一 生长静脉二 绳索动画三 两个球线连接四 扫帚五

HCIA-Datacom H12-811 题库

LDP 邻居发现有不同的实现机制和规定&#xff0c;下面关于LDP 邻居发现的描述错误的是&#xff1a; A&#xff1a;LDP发现机制包括LDP基本发现机制和LDP扩展发现机制 B&#xff1a;LDP基本发现机制可以自动发现直连在同条链路上的LDP Peers C&#xff1a;LDP扩展发现机制够发现…

【Linux】线程(一)

谈论之前需要先谈论一些线程的背景知识 其中就有进程地址空间&#xff0c;又是这个让我们又爱又恨的东西。 注意&#xff1a;全篇都是在32位的情况下进行的 目录 背景知识&#xff1a;地址空间&#xff1a;内存&#xff1a;页表&#xff1a; 基于以上理解文件缓冲区与虚拟地址…

【学术小白成长之路】03三方演化博弈(基于复制动态方程)均衡点与稳定性分析

从本专栏开始&#xff0c;笔者正式研究演化博弈分析&#xff0c;其中涉及到双方演化博弈分析&#xff0c;三方演化博弈分析&#xff0c;复杂网络博弈分析等等。 先阅读了大量相关的博弈分析的文献&#xff0c;总结了现有的研究常用的研究流程&#xff0c;针对每个流程进行拆解。…

代码随想录算法训练营第38天|● 理论基础 ● 509. 斐波那契数● 70. 爬楼梯 ● 746. 使用最小花费爬楼梯

动态规划理论基础 动态规划&#xff0c;英文&#xff1a;Dynamic Programming&#xff0c;简称DP&#xff0c;如果某一问题有很多重叠子问题&#xff0c;使用动态规划是最有效的。 所以动态规划中每一个状态一定是由上一个状态推导出来的&#xff0c;这一点就区分于贪心&…