zoukankan      html  css  js  c++  java
  • 网络编程02

    TIME_WAIT

    TCP 四次挥手,在四次挥手的过程中,发起连接断开的一方会有一段时间处于 TIME_WAIT 的状态

    TIME_WAIT 发生的场景

    只有发起连接终止的一方会进入 TIME_WAIT 状态

    TIME_WAIT 的作用

    TIME_WAIT 的引入是为了让 TCP 报文得以自然消失,同时为了让被动关闭方能够正常关闭;

    TIME_WAIT 的危害

     当在高并发的情况下,TIME_WAIT 状态的连接过多,多到把本机可用的端口耗尽。

    如何优化 TIME_WAIT?

    net.ipv4.tcp_tw_reuse:更安全的设置

    TCP Keep-Alive 选项

    定义一个时间段,在这个时间段内,如果没有任何连接相关的活动,TCP 保活机制会开始作用,每隔一个时间间隔,发送一个探测报文,该探测报文包含的数据非常少,如果连续几个探测报文都没有得到响应,则认为当前的 TCP 连接已经死亡,系统内核将错误信息通知给上层应用程序。

    缺点:如果使用 TCP 自身的 keep-Alive 机制,在 Linux 系统中,最少需要经过 2 小时 11 分 15 秒才可以发现一个“死亡”连接。

    心跳检测

    我们可以通过在应用程序中模拟 TCP Keep-Alive 机制,来完成在应用层的连接探活。

    我们可以设计一个 PING-PONG 的机制,需要保活的一方,比如客户端,在保活时间达到后,发起对连接的 PING 操作,如果服务器端对 PING 操作有回应,则重新设置保活时间,否则对探测次数进行计数,如果最终探测次数达到了保活探测次数预先设置的值之后,则认为连接已经无效。

    什么是 I/O 多路复用

    我们可以把标准输入、套接字等都看做 I/O 的一路,多路复用的意思,就是在任何一路 I/O 有“事件”发生的情况下,通知应用程序去处理相应的 I/O 事件,这样我们的程序就变成了“多面手”,在同一时刻仿佛可以处理多个 I/O 事件。

    select

    使用 select 函数,通知内核挂起进程,当一个或多个 I/O 事件发生后,控制权返还给应用程序,由应用程序进行 I/O 事件的处理。

    缺点:那就是所支持的文件描述符的个数是有限的,默认1024.

    这些 I/O 事件的类型非常多,比如:

    标准输入文件描述符准备好可以读。监听套接字准备好,

    新的连接已经建立成功。

    已连接套接字准备好可以写。

    如果一个 I/O 事件等待超过了 10 秒,发生了超时事件

    poll

    poll 是除了 select 之外,另一种普遍使用的 I/O 多路复用技术,和 select 相比,它和内核交互的数据结构有所变化,另外,也突破了文件描述符的个数限制。

    总结:

    非阻塞 I/O 可以使用在 read、write、accept、connect 等多种不同的场景,在非阻塞 I/O 下,使用轮询的方式引起 CPU 占用率高,所以一般将非阻塞 I/O 和 I/O 多路复用技术 select、poll 等搭配使用,在非阻塞 I/O 事件发生时,再调用对应事件的处理函数。这种方式,极大地提高了程序的健壮性和稳定性,是 Linux 下高性能网络编程的首选。

    epoll

    epoll 可以说是和 poll 非常相似的一种 I/O 多路复用技术,有些朋友将 epoll 归为异步 I/O,我觉得这是不正确的。本质上 epoll 还是一种 I/O 多路复用技术, epoll 通过监控注册的多个描述字,来进行 I/O 事件的分发处理。不同于 poll 的是,epoll 不仅提供了默认的 level-triggered(条件触发)机制,还提供了性能更为强劲的 edge-triggered(边缘触发)机制。

    Linux 中 epoll 的出现,为高性能网络编程补齐了最后一块拼图。epoll 通过改进的接口设计,避免了用户态 - 内核态频繁的数据拷贝,大大提高了系统性能。在使用 epoll 的时候,我们一定要理解条件触发和边缘触发两种模式。条件触发的意思是只要满足事件的条件,比如有数据需要读,就一直不断地把这个事件传递给用户;而边缘触发的意思是只有第一次满足条件的时候才触发,之后就不会再传递同样的事件了。

    epoll 的性能分析

    epoll 的性能凭什么就要比 poll 或者 select 好呢?这要从两个角度来说明。

    第一个角度是事件集合。在每次使用 poll 或 select 之前,都需要准备一个感兴趣的事件集合,系统内核拿到事件集合,进行分析并在内核空间构建相应的数据结构来完成对事件集合的注册。而 epoll 则不是这样,epoll 维护了一个全局的事件集合,通过 epoll 句柄,可以操纵这个事件集合,增加、删除或修改这个事件集合里的某个元素。要知道在绝大多数情况下,事件集合的变化没有那么的大,这样操纵系统内核就不需要每次重新扫描事件集合,构建内核空间数据结构。

    第二个角度是就绪列表。每次在使用 poll 或者 select 之后,应用程序都需要扫描整个感兴趣的事件集合,从中找出真正活动的事件,这个列表如果增长到 10K 以上,每次扫描的时间损耗也是惊人的。事实上,很多情况下扫描完一圈,可能发现只有几个真正活动的事件。而 epoll 则不是这样,epoll 返回的直接就是活动的事件列表,应用程序减少了大量的扫描时间。

    此外, epoll 还提供了更高级的能力——边缘触发。这里再举一个例子说明一下。如果某个套接字有 100 个字节可以读,边缘触发(edge-triggered)和条件触发(level-triggered)都会产生 read ready notification 事件,如果应用程序只读取了 50 个字节,边缘触发就会陷入等待;而条件触发则会因为还有 50 个字节没有读取完,不断地产生 read ready notification 事件。在条件触发下(level-triggered),如果某个套接字缓冲区可以写,会无限次返回 write ready notification 事件,在这种情况下,如果应用程序没有准备好,不需要发送数据,一定需要解除套接字上的 ready notification 事件,否则 CPU 就直接跪了。我们简单地总结一下,边缘触发只会产生一次活动事件,性能和效率更高。

    Reactor 模式是基于待完成的 I/O 事件,而 Proactor 模式则是基于已完成的 I/O 事件

    和同步 I/O 相比,异步 I/O 的读写动作由内核自动完成,不过,在 Linux 下目前仅仅支持简单的基于本地文件的 aio 异步操作,这也使得我们在编写高性能网络程序时,首选 Reactor 模式,借助 epoll 这样的 I/O 分发技术完成开发;而 Windows 下的 IOCP 则是一种异步 I/O 的技术,并由此产生了和 Reactor 齐名的 Proactor 模式,借助这种模式,可以完成 Windows 下高性能网络程序设计。

  • 相关阅读:
    [转]使用RDLC报表
    WPF 导出Excel 导出图片
    细说WPF自定义路由事件
    [转]WPF更换主题
    推荐5款超实用的.NET性能分析工具
    Hibernate框架
    C#的protected internal
    C#的类修饰符和成员修饰符
    C#的foreach
    C#接口
  • 原文地址:https://www.cnblogs.com/520lq/p/14642878.html
Copyright © 2011-2022 走看看