网络通信——基础知识点复习

本文深入解析TCP/IP协议,涵盖三次握手、四次挥手、应用场景、数据传输可靠性保障机制、HTTP请求过程、BIO与NIO、IO多路复用、Netty特性及网络分层等核心内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、TCP三次握手

参考博客 https://blog.youkuaiyun.com/qzcsu/article/details/72861891?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.nonecase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.nonecase

基本概念
1. SYN :同步SYN,在连接建立时用来同步序号。当SYN=1,ACK=0,表明是连接请求报文,若同意连接,则响应报文中应该使SYN=1,ACK=1;
2. ACK :占1位,仅当ACK=1时,确认号字段才有效。
3. seq :序列号,TCP连接中传送的字节流中的每一个字节都按照顺序编号。
4. ack :确认号,期望收到对方下一个报文的第一个数据字节的序号。
大写字母:用于标识位 小写字母:用于标识序号
三次握手流程
1. server建立传输控制块TCB,进入LISTEN(监听)状态。
2. client建立传输控制块TCB, 向server发送连接请求报文,此时SYN = 1, seq = x.此时客户端进入 SYN-SENT(同步已发送)状态(第一次握手)
3. server收到报文后,同意连接,则发出确认报文,此时报文中ACK=1,SYN=1,确认号为 ack = x+1,seq =y(初始化回复报文的序号),此时server进入SYN-RCVD(同步收到)状态。(第二次握手)
4. client收到server的回复之后,发出确认可通信报文,此时报文ACK=1,seq = x+1,ack = y+1,TCP连接建立,客户端进入此时ESTABLISHED(已建立连接)状态,可以通信了。(第三次握手)。
5. 当服务器收到客户端的确认后也进入ESTABLISHED状态,此后双方就可以开始通信了。

在这里插入图片描述
TCP连接为什么是三次握手,不是两次握手?
为防止已失效的连接请求报文突然又传送到了服务端,因而产生错误。

二、TCP四次挥手

  1. client请求断开连接,报文首部 FIN=1,seq=u(u 等于传输数据最后一个字节序号加1),客户端进入FIN-WAIT-1(终止等待1)状态。
  2. server收到断开连接报文,发出确认报文,此时ACK=1,ack = u+1,seq =v(自身的序列号),服务端就进入了CLOSE-WAIT(关闭等待)状态。
  3. client收到server确认报文之后,client进入FIN-WAIT-2(终止等待2)状态。(到这client还会接收server报文,但不会发送报文)。
  4. server将最后数据发送完成之后,向client发送连接释放报文,此时FIN=1,ack = u+1,由于在半关闭状态,server很可能又发送了一些数据,假定此时的序列号为seq=w,此时,server就进入了LAST-ACK(最后确认)状态,等待客户端的确认。
  5. 客户端收到服务器的连接释放报文后,必须发出确认,ACK=1,ack=w+1,而自己的序列号是seq=u+1,此时,客户端就进入了TIME-WAIT(时间等待)状态。注意此时TCP连接还没有释放,必须经过2∗∗MSL(最长报文段寿命)的时间后,当客户端撤销相应的TCB后,才进入CLOSED状态。
  6. 服务器只要收到了客户端发出的确认,立即进入CLOSED状态。同样,撤销TCB后,就结束了这次的TCP连接。可以看到,服务器结束TCP连接的时间要比客户端早一些。
    在这里插入图片描述

三、TCP应用场景

网络会话、文件传输、远程登录

四、TCP如何保证数据传输的可靠性

  1. 校验和:通过比较发送方对数据计算的校验和与 接受方对数据计算的校验和进行比较。
  2. seq与ack:通过序列号seq与确认应答ack来判断是否丢包,因为期望收到对方下一个报文的第一个数据字节的序号,如果不一致则说明丢包。
  3. 超时重传:发送方在发送完数据后等待一个时间,时间到达没有接收到ACK报文,那么对刚才发送的数据进行重新发送。
  4. 连接管理:连接管理就是三次握手与四次挥手的过程
  5. 流量控制:通过TCP协议报文头部信息16位字段的窗口大小来控制,窗口大小的内容实际上是接收端接收数据缓冲区的剩余大小。这个数字越大,证明接收端接收缓冲区的剩余空间越大,网络的吞吐量越大。
  6. 拥塞控制:TCP引入了慢启动的机制,在开始发送数据时,先发送少量的数据探路。探清当前的网络状态如何,再决定多大的速度进行传输。这时候就引入一个叫做拥塞窗口的概念。发送刚开始定义拥塞窗口为 1,每次收到ACK应答,拥塞窗口加 1。在发送数据之前,首先将拥塞窗口与接收端反馈的窗口大小比对,取较小的值作为实际发送的窗口。

四、HTTP请求过程

  1. 域名解析(浏览器自身的DNS缓存 —> Windows系统的DNS缓存 —> hosts文件 —> DNS服务器)查询对应的IP地址
  2. 通过TCP协议与服务器建立连接。
  3. 向服务器发起Http请求
  4. 服务器响应HTTP请求从http请求中解析出客户机要访问的主机名,web应用以及web资源。
  5. 浏览器得到服务器响应的web资源。

五、BIO、NIO

BIO :同步阻塞IO, Socket套接字属于BIO,通过while循环调用accept方法接收客户端连接请求,一旦建立socket进行读写操作就不能接收其他客户端请求,可以通过多线程进行处理多个客户端请求,但是随着开启线程的数目增多,内存资源消耗逐渐增大,导致服务器变慢甚至崩溃。

NIO:同步非阻塞IO,基于缓存读写文件,当一个连接创建后,不需要对应一个线程,这个连接会被注册到selector(多路复用器)上面,所以所有的连接只需要一个线程就可以搞定,但这个线程中的多路复用器进行轮询的时候,发现连接上有请求的话,才开启一个线程进行处理,也就是一个请求一个线程模式。

六、IO 多路复用、select、poll、epoll

文章参考链接https://www.cnblogs.com/jeakeven/p/5435916.html
IO多路复用:IO多路复用是一种同步IO模型,实现一个线程可以监视多个文件句柄;一旦某个文件句柄就绪,就能够通知应用程序进行相应的读写操作;没有文件句柄就绪时会阻塞应用程序,交出cpu。多路是指网络连接,复用指的是同一个线程

select原理: select 函数监视的文件描述符分3类,分别是writefds、readfds、和exceptfds。调用后select函数会阻塞,直到有描述符就绪(有数据 可读、可写、或者有except),或者超时(timeout指定等待时间,如果立即返回设为null即可),函数返回。当select函数返回后,可以通过遍历fdset,来找到就绪的描述符。

select缺点:

  1. 单个进程可监视的 FD(文件描述符,集文件句柄)数量被限制,即能监听端口的大小有限,它由FD_SETSIZE设置,默认值是1024。
  2. 对socket进行扫描时是线性扫描,即采用轮询的方法,效率较低。
  3. 需要维护一个用来存放大量fd的数据结构,这样会使得用户空间和内核空间在传递该结构时复制开销大。

poll原理: poll的机制与select类似,但是poll没有最大文件描述符数量的限制。

poll缺点:

  1. 大量的fd的数组被整体复制于用户态和内核地址空间之间,而不管这样的复制是不是有意义。
  2. poll还有一个特点是“水平触发”,如果报告了fd后,没有被处理,那么下次poll时会再次报告该fd。

epoll原理: 是基于事件驱动的I/O方式,相对于select来说,epoll没有描述符个数限制,使用一个文件描述符管理多个描述符,将用户关心的文件描述符的事件存放到内核的一个事件表中,这样在用户空间和内核空间的copy只需一次。

epoll的优点:

  1. 没有最大并发连接的限制,能打开的FD的上限远大于1024(1G的内存上能监听约10万个端口)。
  2. 效率提升,不是轮询的方式,不会随着FD数目的增加效率下降。
  3. 内存拷贝,利用mmap()文件映射内存加速与内核空间的消息传递;即epoll使用mmap减少复制开销。

六、NIO服务端、客户端序列图

在这里插入图片描述
在这里插入图片描述

七、Netty零拷贝

  1. Netty的接收和发送ByteBuffer采用DIRECT BUFFERS,使用堆外直接内存进行Socket读写,不需要进行字节缓冲区的二次拷贝。
  2. Netty提供了组合Buffer对象,可以聚合多个ByteBuffer对象,用户可以像操作一个Buffer那样方便的对组合Buffer进行操作,避免了传统通过内存拷贝的方式将几个小Buffer合并成一个大的Buffer。
  3. Netty的文件传输采用了transferTo方法,它可以直接将文件缓冲区的数据发送到目标Channel,避免了传统通过循环write方式导致的内存拷贝问题。

八、Netty的线程模型

Netty采用高效的Reactor线程模型,Reactor线程模型有三种

  1. Reactor单线程模型:通过Acceptor类接收客户端TCP连接请求消息,链路建立后,通过Dispather将对应的ByteBuffer派发到指定的Handler上进行消息解码。
    缺点:一个NIO线程同时处理多链路,性能上无法支撑,当NIO线程负载过重,处理速度变慢,可靠性问题(一旦NIO线程死循环会造成节点故障,导致通信不可用)
    在这里插入图片描述

  2. Reactor多线程模型: 增加了一组NIO线程来处理I/O操作。Acceptor线程用于接收客户端TCP连接,
    读写由一个NIO线程池负责。
    缺点:一个NIO线程无法处理并发百万客户端连接,服务端需要对客户端握手进行安全认证,但认证本身消耗性能。
    在这里插入图片描述

  3. 主从Reactor多线程模型:服务端用于接收客户端连接的不再是一个单独的NIO线程,而是一个独立的NIO线程池。
    在这里插入图片描述

九、TCP粘包/拆包发生的原因

  1. 应用程序write写入的字节大小大于套接口发送缓冲区大小
  2. 进行MSS(Maximum Segment Size,最大报文长度)大小的TCP分段
  3. 以太网帧的payload大于MTU进行IP分片
    在这里插入图片描述

十、TCP粘包/拆包解决方案

  1. 消息定长,每个报文大小固定长度,不够位数使用空位补齐。
  2. 在包尾增加回车换行符进行分割(如:FTP协议)
  3. 将消息分为消息头和消息体,消息头包含消息总长度(或消息体总长度)。

十一、Netty提供的解码器

  1. LineBasedFrameDecoder(以标识符\n 或者\r\n为结束位置) + StringDecode(对象转换成字符串) 组合成按行切换的文本解码器
  2. DelimiterBasedFrameDecoder (以分隔符做结束标志的消息的解码器)
  3. FixedLengthFrameDecoder(定长消息的解码器)

十二、编解码技术

远程服务调用RPC时,很少直接使用Java序列化进行消息的编解码和传输,原因如下:
无法跨语言、序列化后的码流太大、序列化性能太低。
业界主流的编解码框架:Google的Protobuf、Facebook的Thrift(适用于静态的数据交换)、JBoss Marshalling

十三、网络七层架构

在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值