epoll

socket采用epoll编程demo

北城以北 提交于 2020-01-10 23:01:04
epoll工作流程 首先,需要调用epoll_create创建epoll; 此后我们就可以进行socket/bind/listen; 然后调用epoll_ctl进行注册; 接下来,就可以通过一个while(1)循环调用epoll_wait来等待事件的发生; 然后循环查看接收到的事件并进行处理; 1)如果事件是sever的socketfd我们就要进行accept,并且把接收到client的socketfd加入到要监听的事件中; 2)如果在监听过程中,需要修改操作方式(读/写),可以调用epoll_ctl来重新修改; 3)如果监听到某一个客户端关闭,那么我就需要再次调用epoll_ctl把它从epoll监听事件中删除。 epoll的结构体 typedef union epoll_data { void *ptr; int fd; uint32_t u32; uint64_t u64; } epoll_data_t; struct epoll_event { uint32_t events; /* Epoll events */ epoll_data_t data; /* User data variable */ }; #include <stdio.h> #include <string.h> #include <sys/socket.h> #include <sys/epoll.h

受”误解“的Java AIO

天大地大妈咪最大 提交于 2020-01-08 18:20:39
【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>> 为什么说 AIO 受”误解“,虽然这个”误解“被打上了双引号,但还是不得不承认它的发展状况并不好。AIO 是 Java 7 开始提供的新特性,而这个”新特性“到如今都成了陈年老酒还鲜有人去品味它。要知道 Java 7 可是在 2011年7月份发布的,市面上基于 AIO 实现的通信框架竟然寥寥无几,关于这项技术的介绍文章也普遍比较粗略。通过阅读那些介绍 AIO 的文章,似乎从学术层面大家就不怎么待见这项技术。 作为 AIO 的学习者、受益者,我觉得有必要先对网上的一些 ”偏见“ 表达一下自己的观点。如果能有幸在认知上搭成共识,之后的学习交流会更加顺畅一点。通常偏见源于比较,AIO 与 BIO、NIO 的对比明细如表所示。 BIO NIO AIO 客户端 : I/O 线程数 1 : 1 N : 1 N : 0 I/O类型 同步阻塞 同步非阻塞 异步非阻塞 API使用难度 简单 复杂 一般 调试难度 简单 复杂 一般 可靠性 差 高 高 吞吐量 低 高 高 适用场景 适用于连接数量不多,并发量不高的场景。充分发挥易编程的优势。 适用于对连接数量以及稳定性、实时性有较高要求的场景,采用 NIO 或 AIO 能有效缓解网络 I/O 造成的机器负载。 同NIO 误解一 通过上表的比较可以看出 AIO 的性价比应该是优于

epoll中的LT和ET读写方式

三世轮回 提交于 2020-01-07 15:11:43
【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>> 可读可写状态 1. 下列四个条件中的任何一个满足时,一个套接口准备好读: a. 该套接口接收缓冲区中的数据字节数 大等于 套接口接收缓冲区的低潮标记,对于 TCP 和 UDP 而言,其缺省值为 1 ; b. 该连接的读这一半关闭,对这样的套接口的读操作将不阻塞并返回 0 ; c. 该套接口是一个监听套接口且已完成的连接数不为 0 ;(就是 accept 成功返回 ) d. 其上有一个套接口错误等待处理,对这样的套接口的读操作将不阻塞并返回 -1 ; 2. 下列四个条件中的任何一个满足时,一个套接口准备好写: a. 该套接口发送缓冲区中的可用空间字节数 大等于 套接口发送缓冲区的低潮标记,对于 TCP 和 UDP 而言,其缺省值为 2048 ; b. 该连接的写这一半关闭,对这样的套接口的写操作将产生 SIGPIPE 信号; c. 该套接口早先使用非阻塞式 connect 以建立连接,并且连接已经异步建立,或者 connect 以失败告终; d. 其上有一个套接口错误等待处理,对这样的套接口的写操作将不阻塞并返回 -1 ; 3.select 与非阻塞 connect 一起使用的时候有以下两个注意点:( 1 )当连接成功建立时,描述字变为可写;( 2 )当连接建立遇到错误时,描述字变为既可读又可写;

linuxepoll和socket非阻塞读

独自空忆成欢 提交于 2020-01-07 14:15:00
【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>> linux version: Linux version 2.6.32-5-686 (Debian 2.6.32-48squeeze4) (dannf@debian.org) (gcc version 4.3.5 (Debian 4.3.5-4) ) #1 SMP Mon Sep 23 23:00:18 UTC 2013 noblock测试代码: epoll使用的是边缘触发模式 view source print ? 01. #include <stdio.h> 02. #include <sys/types.h> 03. #include <sys/socket.h> 04. #include <unistd.h> 05. #include <fcntl.h> 06. #include <sys/epoll.h> 07. #include <netinet/in.h> 08. #include <arpa/inet.h> 09. #include <sys/un.h> 10. #include <sys/ioctl.h> 11. #include <string.h> 12. #include <time.h> 13. #include <sys/time.h> 14. #include <errno.h>

Java NIO && Netty的epoll实现

烂漫一生 提交于 2020-01-07 14:06:27
【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>> Java NIO && Netty的epoll实现 Java NIO Java NIO根据操作系统不同, 针对nio中的Selector有不同的实现: macosx: KQueueSelectorProvider solaris: DevPollSelectorProvider Linux: EPollSelectorProvider (Linux kernels >= 2.6)或 PollSelectorProvider windows: WindowsSelectorProvider 所以毋须特别指定, Oracle jdk会自动选择合适的Selector。 如果想设置特定的Selector,可以属性: -Djava.nio.channels.spi.SelectorProvider=sun.nio.ch.EPollSelectorProvider Netty 自4.0.16起, Netty为Linux通过JNI的方式提供了native socket transport. 使用native socket transport很简单,只需将相应的类替换即可。 NioEventLoopGroup → EpollEventLoopGroup NioEventLoop → EpollEventLoop

Socket分片:基于Netty的Java实现

ε祈祈猫儿з 提交于 2020-01-07 13:05:24
【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>> 最近Nginx发布了1.9.1版,其中一个新的特性就是支持socket的SO_REUSEPORT选项。这个socket的SO_REUSEPORT选项已经有许多现实世界的应用。对NGINX而言,它通过将连接均衡的分给多个进程以提升性能。SO_REUSEPORT已经在一些操作系统上实现了支持。这个选项允许多个socket监听同一个IP地址+端口。内核负载均衡这些进来的sockets连接,将这些socket有效的分片。 尽管Java很早就有一个特性请求:JDK-6432031,但是时至今日,Oracle JDK依然不支持这个选项,因此我们只能通过hack的方式在Java中使用此特性。 Google已经在内部服务器中开启了 SO_REUSEPORT 这个特性: Scaling Techniques for Servers with High Connection Rates ####SO_REUSEPORT 就像聂永的博客中所说: 运行在Linux系统上网络应用程序,为了利用多核的优势,一般使用以下比较典型的多进程/多线程服务器模型: 单线程listen/accept,多个工作线程接收任务分发,虽CPU的工作负载不再是问题,但会存在: 单线程listener,在处理高速率海量连接时,一样会成为瓶颈;

C语言简单实现epoll服务器(一)

*爱你&永不变心* 提交于 2020-01-07 11:08:53
C/S模型 TCP通信C/S模型图如下所示: TCP服务端通信的常规步骤: 使用 socket() 创建 TCP 套接字(socket) 将创建的套接字绑定到一个本地地址和端口上(Bind) 将套接字设为监听模式,准备接收客户端请求(listen) 等待客户请求到来: 当请求到来后,接受连接请求,返回一个对应于此次连接的新的套接字(accept) 用 accept 返回的套接字和客户端进行通信(使用 write() / send() 或 send() / recv() )返回,等待另一个客户请求关闭套接字 TCP客户端通信的常规步骤: 创建套接字(socket) 使用 connect() 建立到达服务器的连接(connect) 客户端进行通信(使用 write() / send() 或 send() / recv() ) 使用 close() 关闭客户连接 epoll函数介绍: int epoll_create(int size) //创建一个epoll句柄,参数size用来告诉内核监听的数目,size为epoll所支持的最大句柄数 int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event) //函数功能: epoll事件注册函数 //参数epfd为epoll的句柄,即epoll_create返回值 /

Nginx 究竟如何处理事件?

浪子不回头ぞ 提交于 2020-01-07 03:43:52
【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>> 在了解了网络事件以及事件分发收集器以后,让我们来了解 Nginx 是怎么样处理事件的? Nginx 事件循环 当 Nginx 刚刚启动时,在 等待事件 部分,也就是打开了 80 或 443 端口,这个时候在等待新的事件进来,比如新的客户端连上了 Nginx 向我们发起了连接,此步往往对应 epoll 的 epoll wait 方法,这个时候的 Nginx 其实是处于 sleep 这样一个进程状态的。当操作系统收到了一个建立 TCP 连接的握手报文时并且处理完握手流程以后,操作系统就会通知 epoll wait 这个阻塞方法,告诉它可以往下走了,同时唤醒 Nginx worker 进程。 接着往下走之后,会去找 操作系统 索要要事件,操作系统会把他准备好的事件,放在事件队列中,从这个 事件队列 中可以获取到需要处理的事件。比如建立连接或者收到一个 TCP 请求报文。 取出以后就会进行 循环处理事件 ,如上就是处理事件的一个循环:当发现队列中不为空,就把 事件取出来开始处理事件 ;在处理事件的过程中,可能又生成新的事件,比如说发现一个连接新建立了,可能要添加一个超时时间,比如默认的 60 秒,也就是说 60 秒之内如果浏览器不向 Nginx 发送请求的话,Nginx 就会把这个连接关掉;又比如说当 Nginx

I/O网络模型

寵の児 提交于 2020-01-06 23:28:10
【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>> 概述 本文从I/O网络模型出发,介绍目前主流的几种网络模型,然后对 同步阻塞I/O、同步非阻塞I/O、I/O多路复用 的机制和流程做了详细的阐述,最后通过一个生活中的例子加深对这3中网络模型机制的理解。 I/O操作 网络IO的本质是socket的读取,socket在linux中被抽象为流,IO操作可以理解为对流的操作。为了操作系统的安全性等考虑,进程是无法直接操作I/O设备的,其必须通过系统调用请求内核来协助完成I/O动作,而内核会为每个I/O设备维护一个buffer。整个请求过程可以概括为:**用户进程发起请求,内核接受到请求后,从I/O设备中获取数据到buffer中,再将buffer中的数据copy到用户进程的地址空间,该用户进程获取到数据后再响应客户端。**如下图所示: 在整个请求过程中,数据从IO设备输入至kernel buffer需要时间,而从kernel buffer复制到用户进程也需要时间(从IO设备到kernel比从kernel到process需要花更多的时间)。因此根据在这两段时间内等待方式的不同,I/O动作可以分为以下五种模式: 阻塞I/O (Blocking I/O) 非阻塞I/O (Non-Blocking I/O) I/O复用(I/O Multiplexing) 信号驱动的I/O

nginx惊群问题的解决方式

為{幸葍}努か 提交于 2020-01-06 15:43:09
【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>> 对于nginx的惊群问题,我们首先需要理解的是,在nginx启动过程中,master进程会监听配置文件中指定的各个端口,然后master进程就会调用 fork() 方法创建各个子进程,根据进程的工作原理,子进程是会继承父进程的全部内存数据以及监听的端口的,也就是说worker进程在启动之后也是会监听各个端口的。关于惊群,指的就是当客户端有新建连接的请求到来时,就会触发各个worker进程的连接建立事件,但是只有一个worker进程能够正常处理该事件,而其他的worker进程会发现事件已经失效,从而重新循环进入等待状态。这种由于一个事件而“惊”起了所有worker进程的现象就是惊群问题。很明显,如果所有的worker进程都被触发了,那么这将消耗大量的资源,本文则主要讲解nginx是如何处理惊群问题的。 1. 解决方式 在前面的文章中,我们讲到,每个worker进程被创建的时候,都会调用 ngx_worker_process_init() 方法初始化当前worker进程,这个过程中有一个非常重要的步骤,即每个worker进程都会调用 epoll_create() 方法为自己创建一个独有的epoll句柄。对于每一个需要监听的端口,都有一个文件描述符与之对应,而worker进程只有将该文件描述符通过 epoll_ctl