【Java ee初阶】网络原理

发布于:2025-05-12 ⋅ 阅读:(18) ⋅ 点赞:(0)

TCP的核心性质

核心性质三连接管理

有连接

连接虚拟的抽象的连接

通信双方各自保存对方的关键信息(IP端口...)

连接如何建立的三次握手

连接如何断开的四次挥手

连接如何建立的  三次握手

handshake计算机术语

客套,打招呼,没有传达实质性的信息,通过打招呼唤起对方的注意

TCP中的握手,传输一个“打招呼”的数据包,这个数据包不携带任何“业务数据”(没有应用层的载荷)

TCP这个数据包只有报头,没有正文

也就是这个操作是不携带任何业务数据

三次握手,建立连接过程中,客户端和服务器要经过三次这样的“打招呼”,连接才能在双方这边都建立好

1)客户端给服务器发起一个syn(同步报文段)

客户端告诉服务器:我要和你建立连接,请你保存我的信息

2)服务器给客户端返回一个ack服务器告诉客户端:收到,我会保存

3)服务器也给客户端发起一个syn服务器也要告诉客户端:我也要和你建立连接请你保存我的信息

4)客户端收到之后,也返回一个ack客户端告诉服务器:收到我会保存

在计算机中,通常一个术语,可能有多种用途需要结合上下文来理解含义

synchronized在多线程中表达的是"互斥"只能有一个在咱们这个TCP这个地方,表达的是"通知"这样的效果

上述过程有四步,但是叫做“三次握手”的原因:

从流程/逻辑上是四次交互,但是中间两次,可以合并成一个TCP数据包

网络上实际只传输了三个数据包

服务器返回ack和发送syn都是内核控制的

和应用程序代码无关(程序员干预不了)

操作系统就可以在同一时间完成这俩数据的传输

三次握手的意义是什么,是用来解决什么问题

三次握手,也可以视为是一种“保证可靠传输的手段”(辅助手段)

  1. 三次握手,相当于“投石问路”,验证通信链路是否畅通
  2. 三次握手,也是在验证通信双方发送能力和接收能力是否正常
  3. 通过三次握手,让通信双方协商关键信息(和可靠性不是很相关,也有用) TCP建立连接过程中,有一个信息是需要协商的,就是TCP数据的起始序号。TCP的序号,针对载荷部分按照字节编号。当TCP连接建立好了之后,传输的第一个数据包的第一个字节的编号,不是从1/0开始编排... 而是在三次握手阶段协商出这样的数字,作为起始编号

三次握手是和可靠传输有关系的

只不过是“前提条件”“辅助操作”真正传输数据的时候,靠的是确认应答和超时重传

编号不从0开始有什么用?

每次建立连接,协商出来的起始编号都是不同的(差别很大)

这样设定的目的,为了避免出现网络传输中的特殊情况

三次握手的意义:

1. 验证通信链路是否畅通

2. 验证通信双方的发送能力和接受能力

3. 协商关键信息

TCP建立连接过程中涉及到的 操作系统的 原生 API (Linux系统提供的C语言风格的api)

在Java里面对上面的api进行了大幅度的简化

我们只需要知道,客户端new Socket对象触发 三次握手

服务器这边通过accept把已经建立好的连接拿到应用程序中(accept接触阻塞的时候,三次握手已经完了)

LISTEN          服务器存在的状态

                      服务器new ServerSocket就会进入到LISTEN表示在“监听”这个端口,端口上过来客                         户端,就能 accept了 

ESTABLISHED 客户端和服务器连接建立好了.

                          客户端和服务器之间就可以进行通信了. 

TCP断开连接(四次挥手)

断开连接的四次挥手,可能是客户端主动发起,也可能是服务器主动发起……

而三次握手,一定是客户端先发起。(倒果为因)

先发起的一方,定义为客户端

  1. 客户端告诉服务器,我要和你断开连接请你把我删了
  2. 服务器回应收到
  3. 服务器告诉客户端,我也要和你断开连接请你把我也删了
  4. 客户端回应收到
  5. 客户端和服务器都会把对方的信息(之前保存的对方的IP和端口)删除掉删除完了,连接就断开了

之所以叫做四次挥手,是因为中间两次交互,是不一定触发合并的(有的时候会合并,有的时候不会)

经典面试题:

建立连接的时候,必须握手三次吗?两次?四次?

四次:可以,但是没必要。

中间两次传输,时机是相同的。

合并成一次,有利于提高效率(封装分用2次 -> 1次)

两次:不可以,2次握手,无法完成“通信双方发送能力,接受能力的验证”

断开连接的时候,必须挥手四次吗?三次?——都可以

四次挥手的意义,就是为了“释放空间” ,建立连接需要保存信息,连接不用了,保存的信息自然就需要释放。

CLOSE_WAIT

被动断开连接的一方进入的状态

收到对方发来的FIN的时候,就会返回ACK,同时进入CLOSE_WAIT状态理解成wait close,等待关闭,等待应用程序代码,调用close

正常情况下,存在的时间会比较短

如果你的服务器,出现了大量的CLOSE_WAIT很可能就是Bug

排查你的代码中是否调用了close

TIME_WAIT

类似于线程TIMED_WAITING,有时间限制的等待

等待连接彻底释放

进入时机主动发起断开连接的一方,进入

我方发送FIN,对方返回ACK

对方发送FIN,我方返回ACK同时进入TIME_WAIT

按理说,我方返回ACK,相当于四次挥手结束了

就可以释放连接了实际上不能立即释放连接,而是要等等

等等,是为了应对最后一个ACK丢包的情况

TIME_WAIT等待时间,称为2 * MSL

MSL:网络上任意两点之间,传输消耗的最大时间 

实际上,MSL给出的是一个 非常宽裕的值 比如Linux上默认是60s

TCP协议中的几个关键状态

LISTEN: 手机开机,信号良好,随时可以打电话

ESTABLISHED: 连接已经建立,电话接通,可以说话了 

CLOSE_WAIT: 等待代码调用close

TIME_WAIT: 等待FIN重传,应对最后一个ACK丢包的情况


网站公告

今日签到

点亮在社区的每一天
去签到