07-Java网络编程

nobility 发布于 2020-01-14 1011 次阅读


网络编程

BIO、NIO、AIO通信机制对比

同步与异步

是被调用方返回处理结果的一种通信机制

  • 同步:调用方发出请求后,处理结束后才会返回
  • 异步:调用方发出请求后,被调用方立即返回,等处理结束后,再使用其他方式返回

阻塞与非阻塞

调用方在等调用结果时的调用状态

  • 阻塞:调用方发出请求后,等待返回的过程中,陷入阻塞状态
  • 非阻塞:调用方发出请求后,等待返回的过程中,可以继续执行其他的任务

BIO、NIO、AIO编程模型对比

BIO

服务端通过ServerSocket.accept()阻塞方法来监听客户端连接,有客户端连接后,创建新的子线程,与获取到的客户端socket进行通信,主线程继续监听客户端连接,主要通过单向的IO Stream来实现数据交换

  • 若不使用线程池,就会导致每个连接都会创建一个新的线程,直到服务器崩溃
  • 若使用线程池控制线程数量,就会导致并发数量的减少,后续连接只能等待前面连接处理完毕后才能进行
  • 所以适用于连接数目少,服务器资源相对多的场景

NIO

使用双向的Channel代替单向的Stream,而且可以是非阻塞式的,也就是单个线程中可以处理多个Channel的IO,其实Channel双向操就是通过Buffer来完成的,从Buffer中读取数据到Channel,从Channel写入数据到Buffer;再使用Selector监控多条Channel的状态,当某个Channel已处于某个状态时,就会触发对应的状态事件,再进行逐个处理;所以编程模式是,服务端通过Selector先监听ServerSocketChannel的accept状态,触发后在调用accept()方法来获取与客户端通信的SocketChannel,并向Selector注册要监听该条SocketChannel读写状态

  • 全部请求都在单一线程中执行,虽然也可以结合多线程实现NIO模型
  • 但是如果前一个请求任务长时间不完成,就会导致后续任务只能等待
  • 所以适用于连接数目多,但是任务执行时间短的场景

AIO

使用异步的Channel代替同步的Channel,可以使用Future对象像同步那样调,也可以使用像JavaScript的Promise异步函数那样调,所以编程模式是,服务端通过向asynchronousServerSocketChannel.accept()传递回调函数,在回调函数中递归监听客户端连接,以及对客户端连接进行处理

  • 对于请求的处理是在异步回调中执行,异步回调是在另一个线程中执行,增加了线程的数量从而减少了任务的阻塞时间
  • 所以适用于连接数目多,任务执行时间长的场景

select、poll、epoll的区别

从操作系统内核层面看,应用程序获取数据需要经历

  1. 将数据通过物理连接送达机器(网卡接收数据)
  2. 将数据拷贝到操作系统内核缓冲区
  3. 从内核缓冲区复制到应用程序缓冲区
  4. 之后才能从应用程序层面取到数据

操作系统层面的IO模型有

  • BIO:应用程序通过系统调用向操作系统内核发出IO请求,如果IO还没准备好,系统调用就会被阻塞,直到IO已经准备好,并且已经拷贝到应用程序缓冲区,系统调用才会成功返回
  • NIO:应用程序通过系统调用向操作系统内核发出IO请求,系统调用会立刻失败返回,告知应用程序IO还没准备好,应用程序需要多次询问操作系统内核,直到IO已经准备好,并且已经拷贝到应用程序缓冲区后,系统调用才会成功返回
  • IO多路复用:应用程序通过系统调用,让操作系统内核,监听一些IO状态变化,如果这些IO的状态未发生变化,该系统调用就会被阻塞,直到某个IO状态发生变化,系统调用才会返回,从而减少了无目的性的询问所带来的开销;select,poll,epoll三个系统函数都是IO多路复用的机制,将用户关心的文件描述符,弄到操作系统内核进行监听
    • select使用数组存储文件描述符,在Linux上单个进程能够监视的文件描述符是1024个
    • poll在select上做了改进,将文件描述符封装成pollfd,以链表形式存储,所以没有上限
    • epoll是使用一个文件描述符,来管理多个文件描述符,将用户关心的文件描述符事件,存放到内核的一个事件表中,从而减少用户空间、内核空间对文件描述符集合的拷贝
  • AIO:应用程序通过系统调用向操作系统内核发出IO请求,该系统调用会立刻失败返回,当IO已经准备好,并且已经拷贝到应用程序缓冲区后,操作系统内核会给该应用程序传递一个信号,来通知应用程序IO已经准备好
此作者没有提供个人介绍
最后更新于 2020-01-14