socket、网络模型笔记

socket、网络模型笔记

Socket是什么?

​ socket是一个文件,也是一个编程模型,本质上是一种管道文件

socket、网络模型笔记_第1张图片

那么既然是一个文件,就会有文件描述符

socket、网络模型笔记_第2张图片

同时也是编程接口(Stub)

socket、网络模型笔记_第3张图片

客户端只有一种socket,即代表服务端的socket,而作为服务端,它有两种socket:

  • Server Socket File
    • 服务端Socket是虚拟抽象出来的概念,它里面存的是客户端Socket的文件描述符,是操作系统提供的编程模型
      • listen(80)
      • clientsocket=serversocket.accept()
  • Client Socket File:代表着连接进来的客户端

I/O多路复用

  • 单线程处理多个Socket

    • 核心问题:内核分发消息

      socket、网络模型笔记_第4张图片

      内核是非常清楚哪个请求发生变动的,当一个客户端连接进来时,内核是最了解的,如上图所示,当第1580号文件发生变动时,内核是很清楚的,但问题来了,内核怎么通知线程,哪个线程才是需要这个消息的线程呢?这时就内核需要分发,如果有了服务端socket文件这种东西,内核只需要把数据给服务端socket文件即可,但还有个问题就是还有很多客户端socket,如果是客户端socket发生了变动内核该通知哪个线程呢

    • select模型:内核不负责推消息,而由线程主动来内核查询,线程维护一个Socket FD的列表

      • 周期性检查是否有FD变动,从客户端来说,有两个维度去思考这个问题,其一是看到Server Socket文件的变动,Server Socket本身就是一个管道文件,所以它只需要不断地从Server Socket中去读取就好了,而Client Socket就需要自行解决了
      • 可以通过循环遍历来检查列表中什么元素状态发生了变化
    • epoll模型:内核维护一个高效的二叉搜索树

      socket、网络模型笔记_第5张图片

      内核一旦知道什么socket发生了变动,它首先通过自己的红黑树找到这个socket的节点,然后再通过这个节点上描述的数据找到对应的事件、对应的线程,再通知对应的线程,效率非常高

      • 已知某个FD发生变化的时候,可以快速知道哪个线程需要处理
  • 通常来说,性能提升归根结底是算法和数据结构需要重新思考

BIO/NIO/AIO

Blocking IO

  • API设计:操作会阻塞线程,而阻塞线程本质上是让线程休眠
    • 如:等待Socket连接
  • 原理:利用CPU中断
    • 阻塞的线程进入休眠,将执行权限交给其他线程
    • 优点:阻塞时不会占用系统资源;程序也好理解
    • 缺点:高并发场景需要较高的线程数量(资源占用);线程切换有成本
  • 适用范围:一般的高并发场景也可以考虑(并行量特别大的场景,如聊天除外)
  • 性能是一个千层饼,是一个综合而复杂的问题,在没有压测之前不要形成任何定论(Jmeter可以用用)

Non-Blocking IO

  • API设计:操作不会阻塞线程

    读不到就返回null

  • socket、网络模型笔记_第6张图片

    原理:由专门的数据结构负责统计发生的I/O,再允许程序监听变更

    • I/O变更发生后,记录在某个特定的数据结构上,比如epoll的红黑树
    • 线程可以在数据结构上注册自己关注的
      • 文件描述符
      • 消息类型(读、写…)
    • 通常给线程提供一个方法可以一次性获得自己关注的事件
      • 如果拿到:一个事件的集合
      • 没有拿到:null

Asynchronous IO

  • API设计:异步编程(基于Future)

    socket、网络模型笔记_第7张图片

    本质:异步转同步

  • 原理:利用线程池技术、协程技术,调度所有Future的计算

    • 通常结合epoll和directmemory技术

N(new)IO

  • NIO的channel设计

    socket、网络模型笔记_第8张图片

  • DirectMapping

    socket、网络模型笔记_第9张图片

    因为经常需要将内核中的数据拷贝到用户空间,所以内核中的数据拷贝其实完全可以由内核做完,由内核创建一个堆外的内存,不是JVM堆里的那个内存,它再将这个内存给到JVM的进程,而这样当数据进到网卡,就由内核帮你将数据拷贝到对堆内存当中,需要用的时候就读这个堆外内存的缓冲区就可以了。

    • 本质是堆外的缓冲区
    • 优化点:减少一次拷贝
  • epoll模型比较适合Non-Blocking(事件驱动)

你可能感兴趣的:(计算机网络,网络,java,aio,nio,bio)