0%

07-网络编程-第二节

省略第一节的 NIO ,后续有时间看

NIO之单线程Reactor模式

略,后续有时间看

网络编程面试-TCP、UDP与HTTP

DDoS攻击是啥?SYN 洪水攻击?

利用合理的服务请求,占用服务资源:带宽攻击和联通性攻击。带宽攻击需要控制大量的肉鸡,SYN 洪泛攻击属于 连通性攻击,发送半连接。

哪些应用适用 UDP 实现?

DNS,直播,多播,可以上层应用自己实现可靠性传输(新的 UDT 协议可以了解一下,Http3 用 UDT)比如广域网中计算中心光纤连接通信

如果应用场景中大多数是简短信息,那么适合用udp实现。因为 udp 是基于报文段的,直接对上层的应用数据封装成报文段然后丢在网络中,如果信息量太大,在链路层会被分片,影响传输效率

http 和 https 的区别?

http 80端口,https 是443端口

是否需要证书

scheme 不同,http 和 https

如果让你来设计QQ,网络协议上如何设计?

  • 登录采用 TCP 协议和 Http 协议:client采用 TCP 向 server 发送信息,Http 协议下载信息。登录后,会有一个 TCP 连接来保持在线状态

  • 好友之间发送消息,主要采用 UDP 协议:利用上层应用层来保证可靠传输,如果发送失败,提示用户发送失败,并可以重新发送。

  • 内网传文件采用 P2P 技术。内网里面可以采用 P2P 技术,不需要服务器中转

TCP粘包的解决

包可能很小,每次都要发送出去得到确认。可以把这些小包合在一起,发送出去,确认一次就行。解决:

  1. 消息头+消息体,消息头用来描述消息的长度,每次读消息先读消息头

  2. 消息定长,每个消息都是一样长

  3. 特殊的分隔符,比如 Netty使用回车换行符来区分

这个比较抽象,老师在视频里面讲了个例子,比如从客户端用 for 语句循环 100 次发送 “james,hello,hahah” 等这些字符串,但是服务端可能说只收到 2 次,因为数据可能粘包,很多数据合在一起发送了,这时候我们没法区分这些次数和数据。如果用 natty 来做的话,会在每次发送后插入 回车换行符,这样,在接收的时候就能根据回车换行符分割。

序列化

阿里的 FastJson 不建议使用,安全问题比较多

ProtocolBuffer 可读性比较差

老师自己平时用的是 Kyro ,说是只能在 Java 语言中使用

select、poll、epoll 的区别

是不是每次都选择 epoll 才是最好的呢?不是,在连接少,用户都活跃的情况,select 和 poll 可能效率更高

直接内存、零拷贝

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

任何语言,你通过socket 发送数据,都需要有一个 缓冲区,先把数据写入缓冲区,之后从缓冲区读取数据到内核发送出去。

如果可以选择,先选直接内存缓冲区,因为直接内存的缓冲区比堆内存的缓冲区肯定是要快的。

那么,为什么会快呢?如果你选择堆上的 Buffer ,那么在发送的时候,还会在直接内存上创建一个 Buffer ,这样一来,首先需要将数据拷贝到堆上的buffer,之后拷贝到 直接内存上的 Buffer ,最后才发送出去;如果是Buffer 直接创建在直接内存上,就没有这个步骤,减少一次拷贝,示意图如下:

直接buffer和堆上buffer

为什么使用堆 Buffer 的时候需要使用到直接内存的 Buffer 呢?因为堆上有GC机制,在 Socket 过程中,数据是不能变化的,如果在中途堆上的 Buffer 被GC 了,那咋办?所以只能再开一个直接内存的 Buffer ,这样 GC 管不着。

在新生代的 GC 是不会去管直接内存的 Buffer 的,只有 Full GC 的时候,才会顺便去回收直接内存的。

所以堆外内存(DirectBuffer)的优劣势在哪?

  • 减少GC 带来的 STW ,增强性能

  • 加快复制速度,如果采用堆内 Buffer 的话,还是需要 DirectBuffer 这个环节,使用 DirectBuffer 可以省略这个步骤

劣势:

  • 产生内存泄漏很难排查

  • 不适合存储很复杂的对象

有哪几种零拷贝方案?

linux 中有好几种:

  • mmap

  • linux 的 sendFile 函数,如果有硬件支持的话,只需要告诉缓存的开始位置和大小,都不用真正将数据复制到 socket 的缓冲区,就能将数据发送出去

  • linux 提供的 splice 方案,不需要硬件支持,使用管道(piple line) 就能将数据直接拷贝到 socket 的缓冲区

不过体现在 JDK 里面就 2 种,一种就是 mmap 方案,还有一种就是NIO 提供的 FIleChannel ,它可以转换为 SocketChannel ,直接将文件通过 socket 发送,这样可以利用 linux 的 mmap 方案做到零拷贝。

问题解答

时间局部性

在一个方法里面使用到了成员变量,在方法里面可能会用局部变量承接这个成员变量,这样就能加快速度

谢谢你的鼓励