Java网络编程知识要点(三)

104 阅读3分钟

1、TCP 粘包/拆包的原因及解决方法?

  • 原因

    • 粘包 Nagle算法影响了每次发送数据的大小,当多次发送小数据,只会再第一次发送小片数据,收到ACK之后尽量将剩余的小片数据整合为一个接近MSS(“最大段大小”)大小的数据包再发送出去。
    • 拆包 还有一种就是当发送的数据超过了MSS的大小,哟与Nagle算法的存在,会将数据拆成两部分。有部分发,有部分放在传冲去
  • 拆包粘包解决方案

    • 数据包投添加长度字段,接收方根据长度字段判断数据包 边界
    • 特殊字符作为数据包开始结束标志
    • 封装为固定长度(空闲空间用0填充)
    • 关闭Nagle算法
    • 发送的数据按照MSS大小分段,一段作为一个数据包。

2、请概要介绍下序列化

序列化时将对象状态转为可保存或可传输的格式的过程

3、Netty是如何解决JDK中的Selector BUG的?

  • 对Selector的select操作周期进行统计,每完成一次空的select操作进行一次计数。
  • 在某个周期内如果连续N次空轮询,则说明触发了JDK NIO的epoll死循环bug。
  • 创建新的Selector,将出现bug的Selector上的channel重新注册到新的Selector上。
  • 关闭bug的Selector,使用新的Selector进行替换。

4、如何让单机下java的应用程序支持几十万乃至百万长连接?

  • 突破局部文件句柄

    • 文件句柄限制 ulimit -n
    • sudo vi /etc/security/limits.conf
    • 末尾加上 软限制和硬限制
      • * hard nofile 1000000
      • * soft nofile 1000000
  • 突破全局文件句柄

      ```
      sodu vi /etc/sysctl.conf
      在/etc/sysctl.conf文件末尾加上下面的内容。
      fs.file-max=1000000
      ```
    

5、select、poll、epoll的区别?

  • select 事件复杂度O(n)。限制为1024或者2048个fd监听数量
  • pool 事件复杂度O(n)。但是没有最大连接数,因为用的链表
  • epoll 复杂度降低到了O(1)。epoll会把哪个流发生了怎样的I/O事件通知我们。没有最大数限制。

6、什么是水平触发(LT)和边缘触发(ET)?

  • 水平触发:
    • 只要文件描述符关联的读内核缓冲区非空,就一直发可读信号。
    • 只要文件描述符关联的写内核缓冲区不满,就一直发可读信号。
  • 边缘触发:
    • 文件描述符关联的读内核缓冲区空转为非空,发一次可读信号。
    • 文件描述符关联的写内核缓冲区空满转为不满,发一次可写信号。

7、直接内存比堆内存快在哪里?

image.png

  • 堆内存 要拷贝到直接内存,才能发。所以直接用堆外内存少一步。
  • 进行网络IO操作其实底层调用的是C的函数write,该函数对应的字节数组的地址不能变化,如果是用java堆作为底层write函数的地址,可能一个gc就把数据从新生代移动到老年代,地址就变化了。

8、啥是零拷贝

  • 计算机执行操作时,CPU不需要先将数据从某处内存肤质到另一个特定区域。
  • 零拷贝基数可以减少数据拷贝次数,提高传输效率。节约CPU周期和内存带宽。
  • 减少用户进程地址空间和内核地址空间之间上下文切换带来的开销
  • 不是不要拷贝是减少不必要的拷贝

9、零拷贝解析

  • DMA 一种允许外围设备直接访问系统主内存的机制。基于DMA,系统主内存与硬盘或者网卡之前的数据传输可以绕开CPU的全程调度。
  • 其实就是sendfile和内存映射

image.png

image.png

image.png

2块缓冲区公用一块物理内存 image.png