TCP/IP 核心概念详解:从网络分层到连接管理

前言

TCP/IP 是一个协议族,是由一系列协议组成的一个网络分层模型,就是一个四层模型。

在讲它是什么之前,我们先来看看为什么要分层?

为什么要分层

简化版的网络结构图:

在上述结构图中,客户端和服务器之间会有很多中间节点,这些节点可能是交换机、路由器或网关。

在理想情况下,客户端往服务器发送一个 HTTP 请求,会有多种路径,而这种路径的选择就叫做"路由"。但由于网络的不稳定性,网络传输的成功率不是也不可能是 100%,所以需要分层。

为什么呢?我来给你解释一下。

请求在传输的过程中,可能因某个节点导致消息的丢失,因此需要一种重传机制:让接收方在收到消息后发送一个回执,表示消息已收到。如果发送方到了指定的超时时间未收到该回执,就认为消息丢失,去重传一次消息。即使接收方已发送回执,而发送方未收到,也不用担心,重复发送消息,并不会导致接收方重复处理,接收方会根据记录识别出重复的消息,并主动抛弃它。

在重传机制中,传输的数据可能会比较大,可能会出现传输时间长、传输失败的概率高等问题。解决办法就是对数据进行分块,这样当某块数据传输失败了,只需单独重传该数据块即可,这样可以降低平均的传输时间,传输失败的概率也更低。

由于有了分块传输,就需要进行分层。因为应用层的协议不只有 HTTP,还有 FTP(传文件)、SMTP(邮件)、DNS(域名服务)。

这些协议都有分块传输的需求,所以需要把分块传输这个通用的功能抽出一层,让这一层只做分块传输:拆分数据块进行分发,接收数据块进行拼装。

此时应用层就不用去分块了,而是只需将要传输的数据交给下层,让它来做这件事;拼装数据也是由这一层来完成,应用层只需接收完整的数据。

数据的补发以及发送失败的回执都是由这一层完成,而这一层叫传输层。TCP(Transmission Control Protocol)传输控制协议是其中的一个协议,它能够保证数据的稳定传输。

有了传输层后,为什么还需要分层?

因为有些场景下,数据并不需要重传。比如游戏数据,在你掉线并重连后,你和其他人是不关心你在掉线时的数据的,只需知道你最新的数据(游戏状态)即可。又比如网络直播,因其实时性,在主播掉线并重连后,我们是不需要知道主播掉线后的画面的,只要知道最新的画面即可。

将数据发送出去,无需确认的这种策略叫 UDP(User Datagram Protocol)用户数据报协议,这是传输层的另一个协议。

TCP 和 UDP 都有一个共同的下层网络需求:都需要让一个数据从一个主机到达另一个主机,所以需要再抽取一层。

此时,传输层不再直接传输数据,只负责拆分、拼装数据,将单个数据块交给下层来完成发送,而这一层叫作网络层。IP 协议就位于此层,负责以最小单位来发送和接收网络数据,以及寻址、路由等工作。

再来梳理一遍数据传输的过程:

有一个 HTTP 请求报文需要从客户端发送到服务器,应用层会将发送报文的任务交给传输层,TCP 会将报文进行拆分,然后将每一份数据块交给网络层,IP 去完成单个数据块的发送,IP 并不需要确保数据发送成功。

等数据到了服务器,网络层会把接收到的数据包逐个交给传输层。传输层在收到某个数据块后,会准备回执发回客户端。如果客户端的传输层在一定时间内没有收到某个数据块的回执,就会执行重传。当服务器的传输层确认接收到了所有完整的数据块后,就会将它们拼装成一条完整报文,发给应用层。

应用层收到消息,就会准备响应报文给客户端... 至此,一次单向数据传输的过程就结束了。

你可能还会疑问,TCP/IP 不应该是有 4 层吗?

其实还有一层,叫做数据链路层,就是以太网、Wi-Fi等。这一层用于给网络提供现实世界中的物理基础和一些规则。

现在我们使用的双绞线是某种网络的底层协议,使用这种网线连接成的网络就叫做以太网。

TCP 连接

什么是连接

连接指的其实就是 TCP 连接,TCP 是一种有状态的连接。双方进行消息交换时,并不需要指明身份,因为在连接时,身份信息就已经保存了。而让通信的双方认识(交换身份信息)的过程就叫做双方的连接。建立连接是为了让双方认识对方并进行通信,不将对方的消息丢弃。

TCP 中有端口的概念,那么它是什么呢?

就是你电脑用于网络通信的端点。比如一次连接中,会有主机 A 的某个端口与主机 B 的某个端口建立连接。在 Java 中,我们通常会使用 Socket (套接字) 来使用端口,你可以把它想象成是一个专用于网络通信的插座,确保数据能在两端间传输。

我们再简单说说 TCP 连接的建立和关闭:

TCP 连接的建立

上图就是"三次握手"的过程:

主动连接方 A 发送 TCP 消息给被连接方 B,表示想要与 B 建立连接。B 收到后会返回一个消息,表示"我知道了,并且我也要和你建立连接"。然后 A 会再发送一条消息给 B,表示"好的,我知道你想要和我建立连接了"。

至此,双方的连接就成功建立了。

TCP 连接的关闭

连接之所以需要关闭,主要是为了节省资源。因为每次建立连接不仅需要在内存中保存对方的信息,还要持续占用主机的端口。

上图就是"四次挥手"的过程:

连接方 A 会先和连接方 B 说"我没有消息要发送了"。B 收到后,会先和 A "我知道了"(这是第二次挥手)。然后,B 会检查自己是否还有数据要发送,等到所有数据都发送完毕后,B 会再发送一条消息给 A 说"我也没有消息要发送了"(这是第三次挥手)。最后,A 会和 B 说"好的,我知道了"(第四次挥手)。

经过这个过程,连接就关闭了。

这里 B 需要回复两次是因为,它在收到 A 的关闭请求时,B 可能有数据还未发完,所以需要先回应 A 的请求,等到数据全发完后,再正式通知 A "可以关闭了"。

长连接

长连接就是连接一直不关闭。

因为理想情况下,所有人的主机都可以互相直连,但实际上,由于内网的存在,有一部分人并不能直接连接外部网络,而是需要通过某个服务器的端口来连接外网,让它帮你转发数据。就比如你手机的数据网络,它就处于内网中,你每次使用时,运营商的网关都会给你随机分配一个内网 IP。

然而,中间的网关为了节省资源,会将长时间不活动的连接关闭。但有时,你需要持续接收消息,需要保证连接不断开,这时就需要用到长连接。

实现长连接的方式叫做心跳,也就是每隔一段时间,就使用 TCP 连接发送一些无意义的短消息给对方,这样网关就不会认为你是空闲连接了。

相关推荐
一条上岸小咸鱼几秒前
Kotlin 基本数据类型(四):String
android·前端·kotlin
Onion_9943 分钟前
学习下Github上的Android CICD吧
android·github
来来走走1 小时前
Flutter Form组件的基本使用
android·flutter
顾林海2 小时前
Android MMKV 深度解析:原理、实践与源码剖析
android·面试·源码阅读
Wgllss3 小时前
雷电雨效果:Kotlin+Compose+协程+Flow 实现天气UI
android·架构·android jetpack
用户207038619495 小时前
Compose 可点击文本:ClickableText Compose 中的 ClickableSpan
android
常利兵5 小时前
Kotlin作用域函数全解:run/with/apply/let/also与this/it的魔法对决
android·开发语言·kotlin
幼稚园的山代王6 小时前
Kotlin-基础语法练习一
android·开发语言·kotlin
闻不多6 小时前
用llamaindex搭建GAR遇到400
android·运维·服务器