小工具知识网

当前位置: 首页 > 行业知识 > TCP/IP协议

行业知识

TCP/IP协议

2026-10-29 22:14:43 来源:互联网转载

✏️作者:银���罐头

系列专栏:JavaEE

“种一棵树最好的时间是十年前,其次是现在”

目录

  • TCP/IP协议
    • 应用层协议
      • 自定义应用层协议
      • DNS
      • 传输层协议
        • 端口号
        • UDP协议
          • UDP协议端格式
          • TCP协议
            • TCP协议段格式
            • TCP工作机制
              • 确认应答(安全机制)
              • 超时重传(安全机制)
              • 连接管理(安全机制)
              • 滑动窗口(效率机制)
              • 流量控制(安全机制)
              • 拥塞控制(安全机制)
              • 延时应答(效率机制)
              • 捎带应答(效率机制)
              • 面向字节流
              • 异常情况
              • UDP 和 TCP 对比
              • 网络层协议
                • IP协议
                  • 地址管理
                  • 路由选择
                  • 数据链路层协议
                    • 以太网
                      • 以太网帧格式
                      • MTU

                        TCP/IP协议

                        应用层协议

                        自定义应用层协议

                        • 为啥要自定义协议?

                          当前的应用程序要解决的业务场景是错综复杂的,不同的公司有不同的业务,不同的业务有不同的流程,业务复杂,要用程序来解决这个复杂的业务,程序也就复杂了。因此很难有一个通用的协议满足所有的业务需求。

                          • 怎样进行自定义协议?

                            1)结合需求,分析清楚请求响应(客户端服务器之间)要传递哪些信息

                            2)明确传递的信息是以什么样的格式来组织

                            可选的方案是很多的。

                            约定好协议得格式内容之后,客户端就能够按照这个格式构造数据并发送,服务器按照这个格式解析处理。

                            约定的协议的内容(传递的信息)是和业务相关性非常大的。但是协议的数据组织的格式(传递的格式)和业务关系不大.

                            典型的用来组织数据的格式:

                            1. XML 标签化的数据组织格式。使用标签来表示键值对,以及树形结构

                            开始标签和结束标签需要成对出现,标签中间的部分就是标签的内容,内容可以是数字,字符串,还可以嵌套放别的标签。

                            HTML 是 XML 的特殊情况

                            XML中标签名字叫啥都是自定义的

                            1. json

                            上述 xml 和 json 都是按照文本的方式来组织的,

                            优点是可读性好,用户不需要借助其他工具,肉眼能看懂。

                            缺点是效率不高,占用较多的网络带宽。

                            xml 要额外传很多标签,json 要额外传很多的key

                            1. protobuffer (谷歌)

                            二进制的表示数据的方式,针对上述的数据信息,通过二进制的形式进行压缩表示了。

                            特点是肉眼观察不了(二进制直接用记事本打开乱码),但是占用空间小了,占用的带宽也就降低了。

                            DNS

                            域名解析系统

                            域名,网址。

                            eg:www.baidu.com

                            要访问网络上的服务器,需要 IP 地址。IP地址不好记,于是就使用一些简单的字符串来表示这个地址。

                            每个域名都对应了 1/N 个IP 地址。

                            最原始的做法,是使用一个 hosts 文件

                            C:\Windows\System32\drivers\etc

                            像 hash 表一样,建立了 IP 和域名之间的映射关系,当然现在打开 hosts 文件,基本都是空的, # 表示注释

                            当访问某个域名的时候,就自动请求下 DNS 服务器,DNS 就会进行查询,将得到的结果(具体的 IP 地址)返回给你。

                            如果你电脑的 DNS 服务器配置的不对,或者 DNS 服务器挂了,此时就会出现一个典型的现象:QQ 能用,但是网页打不开。

                            当前要求网站的域名不能重复(保证唯一)。

                            • 全世界这么多网站,如何保证唯一呢?

                              一级域名,二级域名,三级域名…

                              pic.sogou.com

                              .com(公司) 一级域名,类似的一级域名还有 org,cn,us…

                              sogou 二级域名,表示 搜狗这个公司

                              pic 三级域名

                              域名分级了,DNS 服务器也是分级了,有 一级域名 的 DNS 服务器,还有 二级域名,三级域名…

                              一般常见的就是 三级,四级左右。

                              www.

                              具体 www 算 三级还是 四级还是 五级,看域名具体咋写的,

                              www 是"万维网"的缩写,我们现在使用的这个网络就是 万维网

                              传输层协议

                              端口号

                              端口号:数据库 mysql 默认端口 3306。

                              端口号起到的效果就是区分一个主机上的具体的应用程序。

                              所以,同一台主机上,一个端口号不能被多个进程绑定。

                              使用 IP 地址来区分主机。

                              eg :进程 A 绑定了 3306,此时进程 B 也尝试绑定 3306,进程 B 绑定操作就会失败 (抛异常)

                              端口号是传输层协议的概念,TCP 和 UDP 协议的报头中都会包含 源端口 和 目的端口。

                              TCP 和 UDP 都是用 2 个字节,16 个 bit 位来表示端口号的,一个端口号的取值范围:0 ~ 65535

                              最初学习 C 语言,就得知道不同长度字节数表示的数据范围。

                              1 个字节,8 bit , -128 ~ 127 128 就是 2 ^ 7, 127 就是 2 ^ 7 - 1

                              ​ 0 ~ 255 255 就是 2 ^ 8 - 1

                              2 个字节 , 16 bit, -32768 ~ 32767 32768 就是 2 ^ 15

                              ​ 0 ~ 65535 65535 就是 2 ^ 16 - 1

                              4 个字节,32 bit, -21亿 ~ 21亿

                              ​ 0 ~ 42 亿 9 千万

                              但是自己写程序,绑定的端口号,得是从1024 起的。

                              0 ~ 1023 这个范围的端口称为"知名端口号/具名端口号",这些端口号已经分配给了一些知名的广泛使用的应用程序了。

                              那么我写代码就非要指定 0 ~ 1023 的端口号,行不行呢 ?

                              1.先确定你这个端口号没有被别的程序绑定

                              2.你有管理员权限

                              1023 以下的端口,也不是完全不能用,只是不建议,这些端口虽然被分配给了特定程序,但是这个程序是否在你电脑上运行着,电脑上是否安装了这些程序都是不一定的。

                              UDP协议

                              UDP 的特点:无连接,不可靠传输,面向数据报,全双工。

                              不可靠传输:没有任何安全机制,发送端发送数据报以后,如果因为网络故障该段无法发到对方,UDP协议层也不会 给应用层返回任何错误信息。

                              UDP协议端格式

                              UDP 协议报文结构,这张图,任何一个计算机网络的教科书上都有,而且都是这么画的,但是实际上这么画不够严谨(为了书排版方便,变形了)

                              UDP 就会把载荷数据(就是通过 UDP socket ,也就是 send 方法拿来的数据)再在前面拼装上几个字节的报头,相当于字符串拼接(此处是二进制的,不是文本的)

                              UDP 报头里包含了一些特定的属性,携带了一些重要的信息。不同的协议功能不同,报头中的属性信息不同。

                              对于 UDP 来说,报头 一共 8 个字节,分成 4 个部分(每部分 2 字节)

                              • UDP 报文长度

                                这个长度也是用 2 个字节表示的,2 个字节表示的范围是 0 ~ 65535(64 KB).

                                也就是说一个 UDP 数据报只能传输 64 KB 的数据。

                                报文长度是整个报文的长度,不是载荷长度。

                                如果 应用层数据报超过 64 KB ,怎么办?

                                方案 1: 就需要在应用层,通过代码的方式针对应用层数据报进行手动的分包,拆成多个包通过多个 UDP 数据报进行传输(本来是 send 一次,现在需要 send 多次了)

                                方案2:不用 UDP 了,换成 TCP(TCP 没有这样的限制)

                                • 校验和

                                  作用是验证传输的数据是否是正确的。

                                  网络传输,本质上就是光信号/电信号,这些可能会受到一些物理环境的影响(电场/磁场/高能射线),在这些干扰下可能会出现"比特翻转"的情况。(1->0,0->1)

                                  一旦数据变了,对于数据的含义可能是致命的。

                                  这种现象是客观存在的,不可避免,我们要做的就是及时识别出当前数据是否出现问题。

                                  校验和是针对数据内容进行一系列数学运算,得到一个比较短的结果(2 个字节)。

                                  如果数据内容一定,校验和结果就一定;如果数据变了,得到的校验和结果就变了。

                                  是否有这样的情况,假设数据传输中出错了,但是计算的 校验和 和之前的 校验和 恰好一样?

                                  “要发射导弹” => 0xaabb

                                  “不要发射导弹” => 0xaabb

                                  这个情况理论上存在,工程上出现这种情况的概率极小,忽略不计了。

                                  如果内容相同,得到的校验和一定相同;

                                  如果校验和相同,内容不一定相同(小概率事件)

                                  实际网络传输过程中,往往是把数据的所有字节都参与生成校验和的运算,这样任何一个字节出问题就都能发现了。

                                  针对网络传输的数据来说,生成校验和的算法有很多种。其中比较知名的有几个。

                                  1. CRC

                                  循环冗余校验,把数据的每个字节,循环往上累加,如果累加溢出了,高位就不要了。

                                  好酸但是校验结果不理想,如果数据同时变动了 2 个 bit 位,前一个字节少 1 后一个字节 多 1 这种,就会出现内容变了但是校验和没变这种情况。

                                  1. MD5

                                  MD5 不是简单的相加,有一系列公式来进行更加复杂的数学运算。

                                  MD5算法的特点:

                                  1)定长:无论原始数据多长,得到的 MD5都是固定长度(4/8字节)

                                  2)冲突概率很小:原始数据哪怕只变动一个地方,算出的 MD5 都会差别很大(让 MD5 值更分散了)

                                  3)不可逆:通过原始数据计算 MD5 很容易,通过 MD5 还原成原始数据很难,理论上是不可实现的(计算极大)

                                  MD5 的这些特点使得 MD5 作用更多了:校验和,作为计算 hash 值的方式,加密

                                  1. SHA1

                                  SHA1的特点和 MD5 相同,区别是计算方式不同。

                                  TCP协议

                                  特点是有连接,可靠传输,面向字节流,全双工。

                                  这里的可靠传输是 TCP 的内部机制,和编码关系不大。

                                  TCP协议段格式
                                  • 4位首部长度

                                    TCP 报文 = TCP 报头(首部) header + TCP 载荷 payload/body

                                    一个TCP 报头长度是可变的,不是像 UDP 报头固定是 8 个字节

                                    • 选项

                                      option (选项) , optional (可选的,可有可无的)

                                      此处的选项是对 TCP 报文的一些属性进行解释说明的。

                                      首部长度描述了 TCP 报头有多长,选项之前的长度是固定的(20 字节),首部长度 - 20 = 选项长度

                                      首部长度的单位是 4 字节,

                                      如果首部长度值是 5,表示整个 TCP 报头长度是 20 字节,没有选项;

                                      如果首部长度值是 15 ,表示整个 TCP 报头长度是 60 字节,选项长度是 40 字节

                                      • 保留( 6 位)

                                        reserved

                                        C 语言中,有一类单词,叫做关键字,除了关键字之外,还有一些单词,叫做保留字。

                                        保留字就是现在还没使用,但是保不齐以后要是用,所以现在这占个位置你现在先别用

                                        咱们进行程序开发的时候,其中一个重点考虑的事情就是可扩展性,有些功能可能暂时不需要,保不齐未来需要

                                        • 16 位检验和

                                          和 UDP 校验和同理

                                          TCP工作机制

                                          TCP 是一个复杂的协议,里面有很多机制,这里主要讨论 TCP 提供的 10 个比较核心的机制。

                                          确认应答(安全机制)

                                          TCP 是可靠传输。

                                          可靠,不是说发送方 100% 能把消息发给接收方,而是尽可能把数据传过去,发送方能知道自己的消息是发过去了还是丢了。

                                          确认应答是实现可靠传输的最核心机制。

                                          举个栗子:

                                          张三在追一个女生,有一天张三给女生发消息说"我请你吃饭好嘛?“女生回复他说"好啊”。

                                          当张三收到"好啊"的时候,说明张三发的消息已经顺利被女生看到了(没有丢包)

                                          如果过了好久张三没收到女生的回应,说明丢包了(也可能是已读不回doge)

                                          这里女生回复的"好啊"就称为"应答报文",也叫作 ack(acknowledge)

                                          TCP 进行可靠性传输,最主要考的就是这个确认应答机制。

                                          A 给 B 发了个消息,B 收到之后就会返回一个 应答报文(ACK),此时 A 收到应答之后就知道刚才发的数据已经顺利到达 B 了。

                                          考虑更复杂的情况(发送方发多条消息):

                                          张三可能连续发 2 条消息,张三没等第 1 条消息的回应就发了第 2 条消息。

                                          网络上可能存在"后发先至"的情况,这个情况下收到消息的顺序可能是有变数的。

                                          由于"后发先至",张三先收到了"滚",后收到了"好啊"。

                                          很明显这里应答错乱导致出现歧义。

                                          网络中数据的"先发后至",两个主机之间,路线存在多条,数据报1和数据报2走的都是不同的路线,数据报1的转发路径上的交换机/路由器和数据报2也不一样,有的转发速率快有的转发速率慢,此时这2 个数据报的到达顺序可能会有变数。

                                          网络中的"后发先至"是客观存在的,因此应答报文到达的顺序也是存在变数的,此时就需要考虑如何规避这种顺序错乱带来的歧义。

                                          解决办法是给传输的数据和应答报文都进行编号。

                                          “后发先至”:

                                          eg: 结婚时候新郎的车队可能会后发先至

                                          • 32位序号/确认序号

                                            引入序号之后就不怕顺序错乱了,即使顺序上乱了,也可以通过序号来区分当前应答报文是针对哪个数据进行的。

                                            任何一条数据(包括应答报文)都是有序号的,确认序号则是只有应答报文有(普通报文确认序号里的值无意义)。

                                            报文是否是应答报文,取决于6个标志位中的 ACK,如果 ACK 这个标志位为 1 ,表示是应答报文,如果为 0 表示不是应答报文。

                                            应答报文的序号仅仅是一个身份标识,不需要应答 应答报文,要是应答 应答报文就无限套娃了…

                                            TCP 的序号是按照字节来编写的。

                                            这一条数据是 1000 个字节,假设是从 1 开始编号,此时第一个字节序号就是 1,第 2 个字节序号就是 2…但是由于这 1000 个字节都属于同一个 TCP 报文,TCP 报头里就只记录当前的第1 个字节的序号,此处报头的序号写的是 1。接下来发第 2 条数据,此时第 2 个TCP 数据报的第 1 个字节序号是 1001,如果长度是 1000,此时最后一个字节序号是 2000,这1001~2000都属于一个 TCP 数据报,那么这个TCP 数据报报头的序号就是 1001。

                                            TCP 的字节的序号是依次累加的,这个依次累加的过程对于后一条数据的第 1 个字节序号就是上一条数据的最后一个字节序号再加 1 。每个 TCP 数据报报头只需要填写 TCP 数据 第 1 个字节的序号即可。

                                            TCP 知道了第 1 个字节的序号,再结合报文的长度就可以知道每个字节的序号。

                                            确认序号的取值,是收到的数据的最后一个字节 + 1。

                                            如上图,确认序号写的是 1001,就是在 1000的基础上 +1。

                                            表示的含义:

                                            1. 主机 A 接下来应该从 1001 这个序号开始继续发送

                                            总结:TCP 的可靠传输,最主要就是通过确认应答来保证的,通过应答报文,就可以让发送方清楚地知道传输是否成功,进一步引入了序号和确认序号,针对多组数据进行区分。

                                            超时重传(安全机制)

                                            前面讨论确认应答,只是讨论了顺利传输的情况。如果丢包了呢?

                                            丢包,涉及 2 种情况:

                                            1.发的数据丢了

                                            2.返回的 ack 丢了

                                            发送方看到的结果就是没有收到 ack ,不能区分是哪一种情况。

                                            丢包是一个概率性事件,通常情况下丢包的概率是很小的,因此如果重新发一遍这个数据还是有很大可能传输成功的。

                                            因此 TCP 就引入了 重传机制。

                                            在丢包的时候,重新传一遍数据。

                                            到底这次传输是丢包了,还是 ack 传的慢?

                                            TCP 就引入了时间阈值。

                                            发送方发出数据后,就会等待 ACK,此时开始计时。只要超过了这个时间,不管是丢包了还是 ack 在路上都视为是丢包了。

                                            比如寒假作业,没带等于没写,虽然你写了,你超过了这个规定提交时间就当做没写处理。

                                            超时重传:超过一定时间还没响应就重新传输。

                                            这个超时时间具体是多少 ms ,因为这个时间是可配置的,不同系统上的默认值可能都存在差别。

                                            如果是 ack 丢了这种情况

                                            对于主机 B 来说,1~1000 就收到了 2 次,如果你发的这个数据是一个支付请求?(寄了)

                                            TCP 对于这种重复数据的传输,是有去重处理的,

                                            TCP 存在一个"接收缓冲区"这样的存储空间(接收方操作系统内核里的一段内存),

                                            每个 TCP socket 对象都有一个接收缓冲区(其实也有一个发送缓冲区)

                                            主机 B 收到主机 A 的数据

                                            其实是 B 的网卡读到数据了,然后把这个数据放到 B 的对应 socket 的接收缓冲区(想象成阻塞队列),后续应用程序使用 getInputStream,进一步使用 read,从接收缓冲区里读数据。

                                            在接收缓冲区里,根据数据的序号,TCP 很容易识别当前接收缓冲区里的这 2 条数据是否是重复的,如果重复就把后来的数据丢弃,保证 应用程序调用 read 读到的数据一定是不重复的。

                                            去重可以理解为是一个优先级队列,有序队列。

                                            前面说了,网络上传输的数据可能"后发先至", TCP 利用这个接收缓冲区,对收到的数据重新进行排序,是应用程序 read 的数据都是有序的(保证和发送顺序一致)

                                            根据序号排序,序号相同就去重

                                            eg:结婚当天新郎的车队出现"后发先至",然后车队都到了新娘家门口的时候要整队,排序

                                            这时候我们可以利用前面提到的序列号,就可以很容易做到去重的效果。

                                            总结:由于去重和重新排序机制的存在,发送方只要发现 ACK 没有及时到达,就会重传数据,即使重复了,即使数据乱了,接收方都能去重和排序(依赖 TCP 报头的序号)。

                                            • 重传的数据是否可能又丢包了呢?

                                              有可能,超时重传可能传多次,如果重传好几次都没传过去,此时再重传意义不大了。

                                              从数学角度来理解:

                                              假设一次传输丢包概率是 10%,传输成功概率是 90%;

                                              如果第1次传输丢包,第 2 次传输也丢包了,概率是 10% * 10% = 1%

                                              如果 3 次都丢了,概率是 0.1%

                                              连续重传都丢包,此时的概率原则上讲是非常低的,如果这个情况真的出现了,只能说明此时丢包概率远远不止 10% => 你当前网络出现重大故障

                                              因此,重传达到一定次数时,就不会继续重传,会认为网络出现故障。

                                              接下来 TCP 会尝试 重置连接(相当于断开重连),如果重置还是失败就彻底断开连接了。

                                              具体重传几次 N,也是可配置的,不去研究

                                              重传的时候,第 1 次重传和第 2 次重传,超时时间间隔不一样。一般来说,重传轮次越大,超时时间间隔就越大。超时时间越大,重传频率就越低。(因为重传次数越多,说明重传成功概率越低,此时你重传的太快也是白浪费系统资源)

                                              总结:可靠传输是 TCP 最核心的部分,TCP 的可靠传输就是通过 确认应答 + 超时重传来体现的。其中确认应答描述的是传输顺利的情况;而超时重传描述的传输出现问题的情况。

                                              连接管理(安全机制)

                                              什么是断开连接?

                                              A 和 B 把自己存储的连接信息(数据结构)删除了,连接就断开了。

                                              JDBC 是基于 TCP 建立的连接

                                              连接(Connection)

                                              链接(Link) 快捷方式,比如电脑开始菜单的图标就是快捷方式,比如我想打开 QQ,QQ本来是 在 C 盘某个目录里,我每次打开 QQ 都要到这个目录去找未免太麻烦所以就创建一个快捷方式,这个快捷方式就是一个文件,这个文件里保存了这个可执行文件的真实路径

                                              管理:

                                              就是描述了连接如何创建,如何断开。

                                              TCP 三次握手和四次挥手

                                              滑动窗口(效率机制)

                                              确认应答,超时重传,连接管理,都是给 TCP 可靠性提供的支持。

                                              引入了可靠性,也付出了相应的"代价"(传输效率)

                                              可靠性和效率是冲突的。

                                              因此 UDP 虽然没有 可靠性,但是传输效率比 TCP 高

                                              所以 TCP 在竭尽可能的提高传输效率(本质上是补救措施)。再怎么提高,也不可能比 UDP 这种不考虑可靠性的效率高。

                                              滑动窗口本质上是降低了确认应答,等待 ACK 消耗的时间。

                                              在进行 IO 操作的时候,其实时间成本主要是 2 个部分:

                                              1.等

                                              2.数据传输(数据拷贝)

                                              大多数情况下,IO 操作消耗的时间大部分在"等"上面

                                              举个栗子:

                                              放寒假从学校回家,如果两地比较远,坐飞机回家的情况下。

                                              真正坐飞机的时间很短,但是因为机场一般离市区很远,从学校到机场要花时间,到了机场后换登机牌、托运行李、安检、候机又要花上不少时间,飞机到达目的地,取行李,从机场到家里又要花上不少时间。

                                              这里真正坐飞机的时间就相当于 数据传输的时间,较短。

                                              而其他花在路上的时间,等待时间,比较长。

                                              具体怎么缩短?

                                              批量发送,批量等待,把多份等待时间合并成一份。

                                              滑动窗口的本质就是不等待的批量发送一组数据,然后使用一份等待时间来等待一组数据的多个 ack。

                                              举个例子:

                                              我打算去买肉夹馍,炒饭,烤肠。

                                              方案一:先去买肉夹馍,肉夹馍做好了,再去买炒饭,炒饭做好了,再去买烤肠。

                                              方案二:先去买肉夹馍,不等了立即去买炒饭,也不等立即去买烤肠。

                                              方案一就是用了 3 份等待时间,而方案二只用了 1 份等待时间

                                              把不需要等待,就能直接发送数据的最大的量,叫做"窗口大小"。上面第 2张图里"窗口大小"就是 4000。

                                              当批量发送了 窗口大小的这些数据之后,发送方就要等待 ack 了。

                                              • 啥时候往下发送?等待啥时候结束?

                                                不是说等所有的 ack 都到达才往下发,而是收到一条 ack 就往下发 1 条。(这样就让我们等待的 ack 始终都是 4 条)

                                                在上述情况下,如果丢包了咋办?

                                                1. ack 丢了

                                                上述丢包重传的机制,叫做 “快速重传”(重传操作只重传了丢失的数据)

                                                这个可以视为是 超时重传 机制在滑动窗口下的变形。

                                                如果当前传输数据密集,按照滑动窗口的方式传输,此时就按照快速重传来处理丢包;

                                                如果当前传输数据稀疏,不再按照滑动窗口的方式传输,此时就按照之前的超时重传来处理丢包。

                                                流量控制(安全机制)

                                                是一种干预发送的窗口大小的机制。

                                                滑动窗口,窗口越大,传输效率越高(一份时间等的 ack 越多)。

                                                但是窗口也不能无限大

                                                1.完全不等 ack , 可靠性难以保证

                                                2.窗口太大也会消耗大量的系统资源

                                                3.发送速度太快,接收方接收不过来,发了也白发,接收缓冲区有上限。

                                                接收方的处理能力,是一个重要的约束依据。发送方发的速度不能超过接收方的处理能力。

                                                流量控制就是,根据接收方的处理能力,来协调发送方的发送速率。

                                                如何衡量接收方的处理能力?

                                                一个量化的方法:计算接收方一秒钟能处理多少个字节…(这种方式实现起来有些困难)

                                                更简单的办法:

                                                直接看接收方接收缓冲区里剩余空间的大小。

                                                每次 A 给 B 发了个数据,B 就需要算一下缓存区里剩余空间,然后把这个值,通过 ack 报文返回给 A。

                                                A 就根据这个值来决定接下来发送的速率是多少(窗口大小是多少)

                                                • 窗口大小 16 位,是否意味着,窗口大小最大是 16 kb ?

                                                  不是!

                                                  TCP 为了让窗口更大,在选项部分引入了窗口扩展因子。

                                                  比如窗口大小已经是 64 kb,扩展因子里写了个 2 ,意思就是让 64 kb

上一篇:flashfxp怎么用?

下一篇:Atak下载指南,轻松获取,上手无忧,警惕违法犯罪风险!,旨在突出重点,同时吸引读者的注意力。