linux网络编程学习epoll模型分析(最简单那种哦!!!)

Linux网络编程——epoll原理详解及epoll反应堆模型 设想一个场景:有100万用户同时与一个进程保持着TCP连接,而每一时刻只有几十个或几百个TCP连接是活跃的(接收TCP包),也就是说在每一时刻进程只需要处理这100万连接中的一小部分连接。那么,如何才能高效的处理这种场景呢?进程是否在每次询问操作系统收集有事件发生的TCP连接时,把这100万个连接告诉操作系统,然后由操作系统找出其中有事件发生的几百个连接呢?实际上,在Linux2.4版本以前,那时的select或者poll事件驱动方式是这样做的。 阅读详情

无阻塞

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include<sys/mman.h>
#include<pthread.h>
#include<semaphore.h>
#include <netinet/in.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<sys/select.h>
#include<sys/epoll.h>
#define NAMESIZE 10
#define SERV_PORT 8888
#define MAXLINE 4096
int main()
{
    struct sockaddr_in servaddr,clientaddr;
    socklen_t cliaddr_len=sizeof(clientaddr);
    int listenfd,connfd;
    char buf[NAMESIZE],line[MAXLINE];
    char str[INET_ADDRSTRLEN];

    listenfd=Socket(AF_INET,SOCK_STREAM,0);//创建套接字
    int opt;
    setsockopt(listenfd,SOL_SOCKET,SO_REUSEPORT,(void*)&opt,sizeof(opt));//设置端口复用

    servaddr.sin_family=AF_INET;//设置类型,ip,端口号
    servaddr.sin_addr.s_addr=htonl(INADDR_ANY);
    servaddr.sin_port=htons(SERV_PORT);

    bind(listenfd,(struct sockaddr*)&servaddr,sizeof(servaddr));
    //将servaddr(地址)绑定到套接字上。今天在c++学习竟然发现bind的含义 是适配器。
    listen(listenfd,10);//设置监听上限,但不是真正的监听,监听由accept函数完成
/*前面都是最简单的socket基础哟!!!*/


    struct epoll_event event ,ev;
    int res,len;
    int epfd=epoll_create(20);//创建epoll句柄(红黑树树根)
//  size=20用来告诉内核这个监听的数目一共有多大
    /*接下来我们要想方设法让listenfd上树*/
    event.events=EPOLLIN;//连接到达;有数据来临;
    event.data.fd=listenfd;
    
    /*在上树以前把通信套接字设置为非阻塞*/
    // int flag=fcntl(connfd,F_GETFL);
    // flag|=O_NONBLOCK;
    // fcntl(connfd,F_SETFL,flag);

    epoll_ctl(epfd,EPOLL_CTL_ADD,listenfd,&event);
    //POLL_CTL_ADD 注册、EPOLL_CTL_MOD 修 改、EPOLL_CTL_DEL 删除
    //将套接字挂到树上
    struct epoll_event events[20];
    for(;;){
        // puts("wait");
        int nfds=epoll_wait(epfd,events,20,0);
        // printf("%d\n",nfds);
        int i;
        for(i=0;i<nfds;i++){
            if(events[i].data.fd==listenfd){
                 connfd=accept(listenfd,(struct sockaddr*)&clientaddr,&cliaddr_len);
                if(connfd==-1){
                    sys_err("connfd");
                }
                // int flag=fcntl(connfd,F_GETFL);
                // flag|=O_NONBLOCK;
                // fcntl(connfd,F_SETFL,flag);
                ev.data.fd=connfd;
                ev.events=EPOLLIN|EPOLLET;
                epoll_ctl(epfd,EPOLL_CTL_ADD,connfd,&ev);
                char ip[64]={0};
                printf("received from %s at PORT %d\n",
                    inet_ntop(AF_INET,&clientaddr.sin_addr,str,sizeof(str)),
                    ntohs(clientaddr.sin_port));

            }else{
                if(!(events[i].events&EPOLLIN)) {
                    continue;
                }
                char buf[1024]={0};
                int len=recv(events[i].data.fd,buf,sizeof(buf),0);
                if(len==-1){
                    sys_err("recv");
                }else if(len==0){
                    printf("client disconnected ...\n");
                    int ret=epoll_ctl(epfd,EPOLL_CTL_DEL,events[i].data.fd,NULL);
                    if(ret==-1){
                        sys_err("epoll_ctl");
                    }
                    close(events[i].data.fd);
                }else{
                    printf("recv buf:%s\n",buf);
                    write(events[i].data.fd,buf,len);
                }
            }
        }
    }
    close(listenfd);
    return 0;
}

无阻塞+epoll

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include<sys/mman.h>
#include<pthread.h>
#include<semaphore.h>
#include <netinet/in.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<sys/select.h>
#include<sys/epoll.h>
#include"../head.h"
#define NAMESIZE 10
#define SERV_PORT 8888
#define MAXLINE 4096
int main()
{
    struct sockaddr_in servaddr,clientaddr;
    socklen_t cliaddr_len=sizeof(clientaddr);
    int listenfd,connfd;
    char buf[NAMESIZE],line[MAXLINE];
    char str[INET_ADDRSTRLEN];

    listenfd=Socket(AF_INET,SOCK_STREAM,0);//创建套接字
    int opt;
    setsockopt(listenfd,SOL_SOCKET,SO_REUSEPORT,(void*)&opt,sizeof(opt));

    servaddr.sin_family=AF_INET;//设置类型,ip,端口号
    servaddr.sin_addr.s_addr=htonl(INADDR_ANY);
    servaddr.sin_port=htons(SERV_PORT);

    bind(listenfd,(struct sockaddr*)&servaddr,sizeof(servaddr));//将servaddr(地址)绑定到套接字上。
    listen(listenfd,10);//设置监听上限,但不是真正的监听,监听由accept函数完成



    struct epoll_event event ,ev;
    int res,len;
    int epfd=epoll_create(20);//创建epoll句柄(红黑树树根),size用来告诉内核这个监听的数目一共有多大
    event.events=EPOLLIN|EPOLLET;//连接到达;有数据来临;设置边缘触发
    event.data.fd=listenfd;
    epoll_ctl(epfd,EPOLL_CTL_ADD,listenfd,&event);
    //POLL_CTL_ADD 注册、EPOLL_CTL_MOD 修 改、EPOLL_CTL_DEL 删除
    //将套接字挂到树上
    struct epoll_event events[20];
    for(;;){
        // puts("wait");
        int nfds=epoll_wait(epfd,events,20,0);
        // printf("%d\n",nfds);
        int i;
        for(i=0;i<nfds;i++){
            if(events[i].data.fd==listenfd){
                 connfd=accept(listenfd,(struct sockaddr*)&clientaddr,&cliaddr_len);
                if(connfd==-1){
                    sys_err("connfd");
                }
                
                int flag=fcntl(connfd,F_GETFL);
                flag|=O_NONBLOCK;
                fcntl(connfd,F_SETFL,flag);
				//这里这块是设置通信套接字为无阻塞再上树,因为ET只支持无阻塞
		
                ev.data.fd=connfd;
                ev.events=EPOLLIN|EPOLLET;
                epoll_ctl(epfd,EPOLL_CTL_ADD,connfd,&ev);
                char ip[64]={0};
                printf("received from %s at PORT %d\n",
                    inet_ntop(AF_INET,&clientaddr.sin_addr,str,sizeof(str)),
                    ntohs(clientaddr.sin_port));

            }else{
                if(!(events[i].events&EPOLLIN)) {
                    continue;
                }
                char buf[1024]={0};
                //这个while循环recv。。。
                while(( len=recv(events[i].data.fd,buf,sizeof(buf),0))>0){
                    printf("recv buf:%s\n",buf);
                    write(events[i].data.fd,buf,len);
                }
                if(len==-1){
                    if(errno==EAGAIN){
                        printf("\n缓冲区读完\n");
                    }else
                        sys_err("recv");
                }else if(len==0){
                    printf("client disconnected ...\n");
                    int ret=epoll_ctl(epfd,EPOLL_CTL_DEL,events[i].data.fd,NULL);
                    if(ret==-1){
                        sys_err("epoll_ctl");
                    }
                    close(events[i].data.fd);
                }
                
            }
        }
    }
    close(listenfd);
    return 0;
}
从epoll构建muduo-2 最简单的epoll mini-muduo v 0.01版本,这是mini-muduo的第一个版本,整个程序是一个100行的epoll示例 下面粘贴的代码省略了头文件引用,完整可运行的示例可从github下载,使用命令git checkout v0.01可切换到此版本,在线浏览到这里 #define MAX_LINE 100 #define MAX_EVENTS 500 #define MAX_LISTENFD 阅读详情

相关推荐

C++ - 网络编程模型 - Linux EPOLL

C++ - 网络编程模型 - Linux EPOLL

trojanpizza的专栏 6632

进程线程编程(二)

3 进程间通信   (1)利用pipe()函数创建管道 #include &amp;amp;lt;unistd.h&amp;amp;gt; #include &amp;amp;lt;errno.h&amp;amp;gt; #include &amp;amp;lt;stdio.h&amp;amp;gt; #include &amp;amp;lt;stdlib.h&amp;amp;gt; int main() { int pipe_fd[2];

qdu_huihui的博客 238

我的网络编程学习之路——epoll函数

1. 概述 同 I/O多路复用和信号驱动I/O一样,Linux的epoll(event poll)API可以检查描述符上的I/O就绪状态。epollAPI的主要优点如下。 当检查大量的文件描述符时,epoll的性能延展性比select()和poll()高很多。epoll API既支持水平触发也支持边缘触发。与之相反,select()和poll()只支持水平触发,而信号驱动I/O只支持边

huangjh2017的博客 4138

实验三1

#include "stdafx.h" int main(int argc, char* argv[]) { long int s; int i; s=0; for(i=22;i<=1002;i+=20) { s=s+i; } printf("%d\n",s); return 0; }...

weixin_30252709的博客 443

linux网络编程:深入理解epoll模型

有的朋友可能对select也不是很了解啊,我这里稍微科普一下:网络连接,服务器也是通过文件描述符来管理这些连接上来的客户端,既然是供连接的服务器,那就免不了要接收来自客户端的消息。那么多台客户端,消息那么的多,要是漏了一条两条重要消息,那也不要用TCP了,那怎么办?前辈们就是有办法,轮询,轮询每个客户端文件描述符,查看他们是否带着消息,如果带着,那就处理一下;如果没带着,那就一边等着去。这就是select,轮询,颇有点领导下基层的那种感觉哈。

2401_86353562的博客 1254

科研党必备:Python脚本批量下载DOI文献的保姆级教程(附避坑指南)

本文为科研人员提供了一份详细的Python脚本批量下载DOI文献的教程,涵盖环境配置、核心功能实现、性能优化及常见问题解决。通过自动化脚本,研究者可高效完成文献批量下载,显著提升科研工作效率,特别适合需要处理大量文献的研究团队使用。

weixin_26965807的博客 478

GYFLinux编程实验

创建文件file1,写入字符串“abcdefghijklmn”; 创建文件file2,写入字符串“ABCDEFGHIJKLMN”;读取file1中的内容,写入file2,使file2中的字符串内容为“ ABCDEFGHIJKLMNabcdefghijklmn” #include<stdio.h> #include<stdlib.h> #include<string.h> #include<fcntl.h> #include<errno.h> #in

GYFsix的博客 451

大数据之父_BIM先驱Charles (Chuck) M. Eastman逝世——致敬“BIM之父”

原标题:BIM先驱Charles (Chuck) M. Eastman逝世——致敬“BIM之父”BIM研究的先驱、佐治亚理工教授Charles (Chuck) M. Eastman于本周一(11月9日)在其Atlanta家中逝世。特转韩国Yonsei大学Ghang Lee教授的讣文以作纪念。过世原因未说明。BIM的出现是与当今时代科技的发展分不开的。在信息时代建筑发展面临的挑战巨大:建筑物越建越高...

weixin_39941262的博客 3302

linux网络编程---广播

文章目录举例recvsend 举例 recv #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <signal.h> #include <string.h> #include <errno.h> #include <sys/types....

qq_23929673的博客 271

从USB 2.0到USB 3.x:Synopsys SVT USB VIP配置避坑与接口选择指南

本文详细解析了从USB 2.0到USB 3.x的Synopsys SVT USB VIP配置要点,涵盖协议版本选择、物理接口匹配及UVM层次化架构实现。重点介绍了layering sequence的配置技巧和常见问题解决方案,帮助验证工程师高效避坑并优化验证流程。

weixin_42653691的博客 239

Android13 AudioFlinger混音流程全解析:从prepareTracks_l到threadLoop_write的底层实现

本文深入解析Android13 AudioFlinger混音流程,从prepareTracks_l到threadLoop_write的底层实现。详细剖析MixerThread的核心工作循环,包括音轨预处理、混音算法执行及硬件写入机制,帮助开发者优化音频性能并处理多音轨场景。

tea88的博客 1132

深入linux网络编程(三):异步阻塞IO —— epoll

作者:yurunsun@gmail.com 新浪微博@孙雨润 新浪博客 优快云博客日期:2012年11月17日 <!-- body {font-size:14px; line-height:1.6; color:#333333; font:13px/1.4 Helvetica,arial,freesans,clean,sans-serif} body > *:f

雨润的技术博客 2万+

Ubuntu上通过FinalShell或Asbru访问CentOS虚拟机

使用FinalShell或Asbru远程连接虚拟机

howard2005的专栏 2279

【Linux网络编程】谈谈网络编程中的select、poll、epoll、Reactor、Proactor模型(下)

这个模型也叫做基于线程架构的模型。

theaipower的博客 5770

HDR 人像肤色稳定实战:AE/AWB/ToneMap 冲突解耦与优先级裁决

人像 HDR 最容易“翻车”的就是**肤色飘**:AE 抢亮度、AWB 拉白点、TM 又在肩部压高光,三方各自“对”却合起来“错”。本文给出一套**工程可落地**的裁决策略:以**肤色 ROI 锚点**为最高约束,AE 先对脸部入射照度收敛,AWB 在**肤色先验 + 光源模型**下缓变,TM 采用**色相保持 + 中灰/肤色双锚**且时域一致化。配套**阈值与回归**(ΔE00、亮度漂移 RMS、频闪注入),把“主观对”的口径落到**可度量**,并给出逆光、多脸、霓虹等极端场景的**例外分流**。

努力分享一些人工智能、计算机视觉、影像等相关的知识干货! 1206

华为od统一考试B卷【宜居星球改造计划】Java&Go 实现

XXX年,人类通过对火星的大气进行宜居改造分析,使得火星已在理论上具备人类宜居的条件,由于技术原因,无法一次性将火星大气全部改造,只能通过局部处理形式,假设将火星待改造的区域为row * column的网格每个网格有3个值,宜居区、可改造区、死亡区,使用YES、NO、NA代替,YES表示该网格已经完成大气改造,NO表示该网格未进行改造,后期可进行改造,NA表示死亡区,不作为判断是否改造完成的宜居,无法穿过 初始化下,该区域可能存在多个宜居区,并且每个宜居区能同时在每个太阳日单位向上下左右四个方向的相邻格子进

MISAYAONE的博客 1万+

[Linux网络编程]高并发-Epoll模型

Epoll模型的三个函数 函数原型+功能说明 (1)epoll_create()参数使用 (2)epoll_ctl()参数使用 (3)epoll_wait()参数使用 Epoll和Select区别对比 Epoll模型封装成类 Epoll简单实现打印 代码+解释

weixin_44972997的博客 3112

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

网络编程中epoll模型

epoll的两种模式ET和LT模式水平触发: 高电平代表1​ 只要缓冲区中有数据, 就一直通知边缘触发: 电平有变化就代表1​ 缓冲区中有数据只会通知一次, 之后再有数据才会通知.(若是读数据的时候没有读完, 则剩余的数据不会再通知, 直到有新的数据到来)

m0_65948738的博客 1487

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

Linux网络编程--epoll 模型原理详解以及实例

1.简介Linux I/O多路复用技术在比较多的TCP网络服务器中有使用,即比较多的用到select函数。Linux 2.6内核中有提高网络I/O性能的新方法,即epoll 。 epoll是什么?按照man手册的说法是为处理大批量句柄而作了改进的poll。要使用epoll只需要以下的三个系统函数调用: epoll_create(2),epoll_ctl(2),epoll_wait(2)。

志存高远 1万+

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

【Linux网络编程】多路转接之epoll

epoll接口解析,内核中epoll模型理解,代码编写

2303_80828380的博客 1048

Linux网络编程---I/O复用模型之epoll

Linux网络编程—I/O复用模型之epoll1. epoll模型简介epoll是Linux多路服用IO接口select/poll的加强版,e对应的英文单词就是enhancement,中文翻译为增强,加强,提高,充实的意思。所以epoll模型会显著提高程序在大量并发连接中只有少量活跃的情况下的系统CPU利用率。 epoll把用户关心的文件描述符上的时间放在内核的一个事件表中,无需像select和po

men_wen的博客 1万+

网络编程-epoll学习

难点就在结构体的void*arg,它就是本身这个结构体本身。

chocochato的博客 1291

网络编程——epoll

参考 《TCP/IP网络编程》 尹圣雨 epoll epoll也是Linux下实现I/O复用的一种方法,其性能优于select。 基于select的I/O复用服务器的设计缺陷 调用select函数后,针对所有文件描述符的循环语句。调用select函数后,需要观察作为监视对象的fd_set变量的变化,找出变化的文件描述符,因此需要针对所有监视对象的循环语句。 作为fd_set变量会发生变化,调用select函数前需要复制并保存原有信息,并在每次调用select函数时传递新的监视对象。 其中,第

beilizhang的博客 4336

Linux——网络编程(epoll、epoll反应堆、心跳、线程池)

1,epoll函数 epoll是Linux下多路复用IO接口select/poll的增强版本,它能显著提高程序在大量并发连接中只有少量活跃的情况下的系统CPU利用率,因为它会复用文件描述符集合来传递结果而不用迫使开发者每次等待事件之前都必须重新准备要被侦听的文件描述符集合,另一点原因就是获取事件的时候,它无须遍历整个被侦听的描述符集,只要遍历那些被内核IO事件异步唤醒而加入Ready队列的...

一个小孩 4496

linux网络编程(2)I/O多路复用 、epoll使用详解

在while循环中使用epoll_wait不断去查看已被监听的套接字的事件,获取到事件后,在for循环中处理这些事件。如果是listenfd的事件,那么接收并创建一个clientfd,并将此fd的可读事件添加到epoll,让epoll管理此clientfd;epoll_wait的功能是阻塞一段事件,直到timeout时间到达或者epoll上监听的套接字有关注的事件发生,并且返回阻塞这段时间内发生事件的socket数量。一般来说,在我们的网络服务器程序中,套接字分为两大类,监听套接字和客户端套接字。

qq_44158081的博客 1746
上一篇: 有关c++ istringstream的一个坑
下一篇: linux下可以帮你把头文件和main函数写好的mytouch
adlatereturn
博客等级 码龄7年 883粉丝 45原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值