Java学习笔记之TCP/IP协议篇

前言

学好计算机网络首先地对它的体系结构有一定的了解。

OSI七层协议:物理层、数据链路层、网络层 、传输层(主机间的数据传输)、会话层、表示层、应用层

TCP/IP概念模型:链路层、网络层、传输层、应用层

TCP和UDP的简介与区别

TCP又称传输控制协议,面向连接、可靠、基于字节流的传输层通信协议,将应用层的数据流分割成报文段并发送给目标节点的TCP层。(数据包都有序号,已接收会发送ACK(acknowledgment number)确认否则重传;发送和接收是都会进行校验)

其报文结构如下:
Java学习笔记之TCP/IP协议篇
TCP/IP处理数据头部(发送部分):

  1. 在应用层把HTTP数据添加TCP首部传输到传输层
  2. 在传输层中读取TCP首部并添加IP数据包往网络层传输
  3. 在网络层根据IP首部添加网络架构(以太网首部)进而传到链路层中

UDP

  • 面向非连接;
  • 支持同时向多个客户端传输相同的消息;
  • 报头只有8个字节开销较小;
  • 吞吐量只受数据生成速率、传输速率和机器性能的限制;
  • 不保证可靠交付,无需维持复杂的链接状态表;
  • 面向报文,不对提交的报文信息拆分或合并。

其报文结构如下:
Java学习笔记之TCP/IP协议篇
TCP和UDP的区别:

TCP UDP
面向连接 无连接
可靠性强 不可靠
用***保证数据的有序交付 无有序性
速度慢 速度快
重量级(20个字节) 轻量级(8个字节)

重头戏之TCP的三次握手和四次挥手

前期概念

TCP Flags:URG(紧急指针标志)、ACK(确认序号标志)、PSH(push标志)、RST(重置连接标志)、SYN(同步序号,用于建立连接过程)FIN(finish标志,用于释放连接)

TCP的三次握手
Java学习笔记之TCP/IP协议篇

  1. 建立连接时,客户端A发送SYN包(SEQ=100)到服务器B,进入SYN_SEND状态,等待服务器B确认;
  2. 服务器B收到SYN包,确认客户的SYN(ACK=SEQ+1=101),同时自己也发送一个SYN包(SEQ=300),即SYN+ACK包,此时服务器进入SYN_RECV状态;
  3. 客户端A收到服务器B的SYN+ACK包,向服务器发送确认包ACK(ACK=SEQ+1=301),包发送完毕后,服务器B和客户端A进入ESTABLISHED状态,三次握手完成。

三次握手建立连接的原因:初始化SEQ的初始值(sequence number)

问题1:当服务器收到客户端的SYN,回复SYN+ACK包时未收到ACK确认会导致服务器不停重试到超时结束。从安全的角度上说,此种情况容易被人不断只发SYN包导致服务器一直超时正常用户无法使用业务。

解决方案:引入tcp_syncookies参数在SYN队列满时回发SYN Cookie,正常的连接则会回发SYN Cookie来实现连接的建立。

问题2:建立连接完成后,客户端发生故障怎么办?

解决方案:利用保活机制,服务器继续向客户端发送保活探测报文,如未响应则继续发送直至保活探测数但仍未收到响应后中断连接。

TCP的四次挥手
Java学习笔记之TCP/IP协议篇

  1. 客户端发送一个FIN,用于关闭客户端到服务器的数据传送,客户端进入FIN-WAIT-1状态;
  2. 服务器收到FIN后,发送一个ACK给客户端,ack=u+1(与SYN相同,一个FIN占用一个序号),服务器进入CLOSE-WAIT状态;
  3. 服务器发送一个FIN,用于关闭服务器到客户端的数据传送,服务器进入LAST-ACK状态;
  4. 客户端收到FIN后,客户端进入TIME-WAIT状态,接着发送一个ACK给服务器,ack=w+1,服务器进入CLOSED状态,四次挥手完成。

问题1:为什么会出现TIME-WAIT状态?

:(1)因为这样能保证有足够的时间让对方(具体情况下不一定是客户端提出断开连接)收到ACK包;
(2)避免了新旧连接混淆。

问题2:为什么四次挥手才能断开连接?

:由于发送方和接收方是全双工通信,都需要FIN报文和ACK报文。

问题3:Linux中服务器出现大量CLOSE-WAIT状态的原因?

:由于对方关闭socket连接,我方忙于读或写,没有及时关闭连接,所以需要检查代码(重点看释放资源方面)或检查配置(重点看处理请求的线程方面)。

额外的一些概念

RTT:发送一个数据包到收到对应的ACK所花费的时间。
RTO:重传时间间隔。

TCP的滑动窗口:用于流量控制和乱序重排以确保TCP的可靠性和流控特性。

TCP会话的发送方

  1. 已发送已得到端回应;
  2. 已发送未得到端的回应;
  3. 未发送但允许发送;
  4. 未发送达到窗口的阈值不允许发送。

TCP会话的接受方

  1. 已接收已发回执;
  2. 未接收但可接收;
  3. 未接收且已达到窗口阈值不能接收。