Java网络编程

基本概念

网络IO会涉及到同步,异步,阻塞,非阻塞等几个概念。一个网络IO读取过程是数据从 网卡 到 内核缓冲区 到 用户内存 的过程。同步和异步区别在于数据从内核到用户内存的过程是否需要用户进行等待。

常见的网络IO模型

Unix环境下经典的IO模型包括:同步阻塞,同步非阻塞,IO复用,信号量驱动,异步非阻塞 这5种。

同步阻塞:网络编程中,读取客户端数据需要调用recvfrom。默认情况下这个调用会一直阻塞到数据接收完毕,是个同步阻塞的IO。

同步非阻塞:这种编程中将socket设置成O_NONLOCK即可,只对于网络IO有效,对于磁盘IO无效。是一个不断主动轮训获取的过程的方式。

IO复用:是一种进程预先告知内核的能力,让内核发现进程指定的一个或多个IO条件就绪,然后通知进程,使得进程能在一连串的事件进行等待。

多路复用涉及到:select,poll和epoll。select和poll原理基本相同:

  • 注册监听的fd,这里的fd创建时最好使用非阻塞。
  • 每次调用都会区检查这些fd的状态,当一个或多个fd就绪时返回。
  • 返回结果中包括已经就绪和未就绪的fd。

select单个进程打开fd的数量是有限的,select受限于FD_SIZE。poll通过pollfd数组向内核传递需关注的事件,避开文件描述符限制。

select和poll包括大量的fd数组的被整体复制于用户态和内核态空间地址之间,开销随着fd数量增加而增加。

多路复用中的事件驱动是epoll实现的:

  • 基于事件驱动方式,避免每次把所有fd数组扫描一遍。
  • epoll_wait只返回有效的fd。
  • epoll使用nmap内存映射技术避免内存复制的开销。
  • epoll的fd数量上限是操作系统的最大fd数量,这个数量和内存无关,通常大于1024。

信号量驱动:在事件完成之后,通过信号量通知进程。

  • 开启套接字信号量驱动IO功能。
  • 系统调用sigaction执行信号量处理函数,非阻塞的可以立即返回。
  • 数据就绪,生成sigio信号,通过信号回调通知应用来读取数据。

但是Linux信号量队列是有限的,如果超出了的信号数据是无法读取的。

异步非阻塞:

这种方式是内核处理好数据,不需要用户进程来获取,而是直接发送到用户进程中。

Java中对应的网络编程模型

有BIO,NIO,AIO。

一般不用了解,直接上Netty就可以了。

原文发布于微信公众号 - 春哥叨叨(chungedaodao)

原文发表时间:2019-04-22

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券