目录
[1. TCP-IP五层模型](#1. TCP-IP五层模型)
[2. UDP协议](#2. UDP协议)
[2.1 特点](#2.1 特点)
[2.2 UDP协议端格式](#2.2 UDP协议端格式)
[2.3 校验和](#2.3 校验和)
[3. TCP协议](#3. TCP协议)
[3.1 特点](#3.1 特点)
[3.2 TCP协议段格式](#3.2 TCP协议段格式)
[3.2.1 首部长度](#3.2.1 首部长度)
[3.2.2 选项](#3.2.2 选项)
[3.2.3 保留6位](#3.2.3 保留6位)
[3.3 TCP内部的工作机制](#3.3 TCP内部的工作机制)
[3.3.1 确认应答](#3.3.1 确认应答)
[3.3.2 超时重传](#3.3.2 超时重传)
[3.3.3 连接管理](#3.3.3 连接管理)
[3.3.4 滑动窗口](#3.3.4 滑动窗口)
1. TCP-IP五层模型
应用层-数据具体要怎么使用。
传输层-只考虑起点和终点。
网络层-负责任意两个结点之间的传输、路径规划。
数据链路层-负责相邻节点间的数据传输。
物理层-信息传输的公路。
下面的四层都是在系统内核/驱动程序/硬件中已经实现好的,只能了解不能修改。应用层协议是可以自定义的。自定义协议主要是做两件事:
1.明确协议数据要传递哪些信息(根据需求来的)
2.明确数据组织格式,比如按照纯文本的方式,也可以使用xml、json、protobuffer
应用层除了上述自定义的协议之外,也有一些大佬们设计好的现成的协议,最典型的就是http协议。
传输层虽然是操作系统内核已经实现好了,但是程序员写代码,要调用系统提供的socket api完成网络编程的,socket就是属于传输层的部分。
端口号是传输层协议的概念,TCP和UDP协议报头中都会包含源端口和目的端口,这俩都是使用2个字节,16个比特位表示的。
需要熟背的内容
1个字节 8 bit 范围 -128到+127 0-255
2个字节16bit 范围-32768到+32767 0-65535
4个字节 32bit 范围 -21亿到+21亿 0-42亿9千万
一个端口号的取值范围是0-65535,但是自己写的程序绑定的端口号得是从1024起的。
0-1023这个范围的端口,称为"知名端口号/具名端口号",这些端口号是属于已经分配给了一些知名的广泛使用的应用程序了。
端口号:数据库mysql默认端口3306,起到的效果就是区分一个主机上具体的应用程序,要求在同一个主机上,一个端口号不能被多个进程绑定。
2. UDP协议
2.1 特点
无连接、不可靠、面向数据报、全双工。
2.2 UDP协议端格式
一次网路通信涉及到五元组:源IP、源端口、目的IP、目的端口、协议类型
UDP报头里包含了一些特定的属性,就携带了一些重要的信息。不同的协议,功能不同,报头中带有的属性信息也不同,对于UDP来说,报头一共就是8个字节。分成4个部分(每个部分两个字节)。
16位UDP长度,表示整个数据报(UDP首部+UDP数据)的最大长度;2个字节,范围0-65535;换算单位为64KB,一个UDP数据报最大只能传输64KB的数据。如果应用层数据报超过64KB,咋办?
(1)就需要在应用层,通过代码的方式针对应用层数据报进行手动的分包,拆分成多个包通过多个UDP数据报进行传输(本来需要send一次,现在需要send多次)
(2)不用UDP,换成TCP(TCP没有这样的限制)
2.3 校验和
如果校验和出错,就会直接丢弃。
校验和的作用是验证传输的数据是否是正确的;网络传输过程中,可能会受到一些干扰,在这些干扰下就可能出现"比特翻转"的情况。网络传输的本质是光信号/电信号,就会受到一些物理环境的影响,所以就引入了校验和来进行鉴别,针对数据内容进行一系列的数学运算,得到一个比较短的结果,如果数据内容一定,得到的校验和结果就一定,如果数据变了,得到的校验和也就变了。
针对网络传输的数据来说,生成校验和的算法有很多种,其中比较知名的几个:
1.CRC
循环冗余检验
简单粗暴,把数据的每个字节,循环往上累加,如果累加溢出了,高位就不要了。【优点:好算,但是校验效果不是特别理想,万一数据同时变了两个比特位,就容易出现内容变了,CRC没变这样的情况】
2.MD5
不是简单相加,有一系列公式,来进行更复杂的数学运算(数学问题)
特点:
(1)定长,无论原始数据多长,得到的MD5值都是固定长度(4字节版本,也有8字节版本)
(2)冲突概率很小,原始数据哪怕只变动一个地方,算出的MD5值都会差别很大(让MD5结果更分散了)
(3)不可逆。通过原始数据计算MD5很容易,通过MD5还原成原始数据很难,理论上是不可实现的。
MD5的特点让它的作用更多了:校验和、作为计算哈希值的方式、加密。
3.SHA1
3. TCP协议
TCP Transmission Control Protocol 传输控制协议
3.1 特点
有连接、可靠、面向字节流、全双工
3.2 TCP协议段格式
3.2.1 首部长度
一个TCP报头,长度是可变的,不是像UDP一样固定是8个字节。因此,首部长度就描述了TCP报头具体多长。另外选项之前的部分是固定长度(20字节:一行是4个字节)
【此处的首部长度是4比特位】
3.2.2 选项
首部长度 - 20 字节得到的就是选项部分的长度。
如果首部长度值是5,表示整个TCP报头的长度是20字节【相当于没有选项】
如果首部长度值是15,表示整个TCP报头是60字节【选项长度相当于是40字节】
3.2.3 保留6位
保留6位是为了以后的扩展来考虑的,对于网络协议来说,扩展升级,是一件成本极高的事情,比如UDP,报文长度是2字节,因此一个包最大就是64KB,现在是否可以能把UDP协议升级,让他支持更大的长度,比如把报头长度使用4字节表示??
理论上可行但实际的操作成本极高。这不是技术问题,而是营销问题。需要升级设备中的操作系统。但是如果引入"保留位",此时升级操作的成本就会降低不少,如果后续TCP引入了一些新的功能,就可以使用保留位的字段,此时对于TCP本来的报头结构的影响比较小,老的设备即使不升级,也可以兼容。
3.3 TCP内部的工作机制
3.3.1 确认应答
**实现可靠传输最核心的机制。**可靠不是说发送方百分百可以将消息发给接收方,而是尽可能的把数据进行传输,同时如果还是传输不过去,至少能知道。
(1)应答报文ack
ack = 1 -- 应答报文
任何一条数据(包括应答报文)都是有序号的,确认序号,则是只有应答报文有(普通报文确认序号字段里的值无意义)
应答报文中确认序号填写的是1001,就是在数据1000上+1,表示的含义
a.小于1001的数据都已经确认收到了
b.A接下来该从1001这个序号开始继续发送
(2)小结
TCP可靠传输能力,最主要的就是通过确认应答机制保证的。通过应答报文,就可以让发送方清楚的知道是否传输成功,进一步引入序号和确认序号,针对多组数据进行详细区分【网络上可能存在"后发先至"这个情况下,收到的消息的顺序可能是存在变数的】。
3.3.2 超时重传
超过一定的时间没响应,就重新传输。
TCP对于重复数据的传输有特殊的处理【去重】
TCP存在一个"接收缓冲区",这样的存储空间【接收方的操作系统内核里的一段内存】
对确认应答一个重要补充:一旦出现丢包的情况,就要重新进行传输。发送方卡一个超时时间,指定时间范围内都没有收到ack,此时就认为丢了,需要重传。【数据报丢了:直接重传。ack丢了:就说明接收方会收到两份一样的数据,tcp会根据序号针对收到的消息进行去重】
3.3.3 连接管理
连接【Connection】:抽象的概念。
意义:
通信双方各自建立对对方的"认同"
验证通信双方各自的发送能力与接收能力是否ok
在握手的过程中,双方协商一些重要参数。
三次握手:syn【尝试建立连接】 ack【应答】 四次交互,中间两次交互可以合二为一。
四次挥手:断开连接。通信双方各自给对方发送一个FIN【结束报文段】,再各自给对方返回一个ack【由于中间的两次时间并不尽相同,ack是立即返回的,下一条FIN是代码里执行到close方法,才触发的,因此是四次,如果中间间隔真的很短或者加上了延迟应答这样的机制,四次挥手也是可能会合并成三次的】
理解:TIME_WAIT
出现在主动发起断开连接的一方客户端需要等待一个2MSL【互联网上两个结点之间的数据传输消耗的最大时间】(Max Segment Life,报文最大生存时间)的时间,才会进入CLOSDE状态。
3.3.4 滑动窗口
一发一收的方式性能较低,一次发送多条数据就可以大大提高性能。(将多个时段的等待时间重叠在一起了)提升效率不等于高效。确认应答、超时重传、连接管理保证了TCP的可靠性。【可靠性和传输效率本身是矛盾的】
窗口大小
无需等待确认应答而可以继续发送数据的最大值。
操作系统内核为了维护这个滑动窗口,需要开辟发送缓冲区来记录当前还有哪些数据没有应答;只有确认应答过的数据,才能从缓冲区删掉。
窗口越大,网络的吞吐率就越高。
能够根据接收方的处理能力制衡发送方的发送速率
滑动窗口的本质是降低了确认应答、等待ACK的时间。【进行IO操作的时候,时间成本主要是两个部分等待和数据传输。大多数情况下都是在等】
出现了丢包,如何进行重传?【分两种情况讨论】
a.数据包已抵达,ACK被丢了
ack丢了不要紧,因为可以通过后续的ACK进行确认。
b.数据包直接丢了
当一段报文段丢失之后,发送端会一直收到1001这样的ACK,就像是在提醒发送端"我想要的是1001"一样。
如果发送端主机连续三次收到了同样的一个"1001"这样的应答,就会将对应的数据1001-2000重新发送。
这时接收端收到1001之后,再次返回的ACK就是7001(2001-7000接收端其实之前就已经收到了,被放到了接收端操作系统内核的接收缓冲区中)
这种机制也叫做"高速重发控制"【快重传】--超时重传机制在滑动窗口下的变形。
3.3.5流量控制
一种干预发送窗口大小的机制。
滑动窗口,窗口越大,传输效率越高,但是窗口不能无限大。
(1)完全不等ACK可靠性就不能保障
(2)窗口太大,消耗系统资源
(3)发送速度太快,接收方处理不过来,发了也白发。
约束依据:接收方的处理能力。
接收方处理数据的速度是有限的,如果发送端发的太快,导致接收端的缓冲区被打满,这个时候发送端继续发送,就会造成丢包,继而引起丢包重传等一系列连锁反应。
因此TCP支持根据接收端的处理能力,来决定发送端的发送速度,这个机制就叫做流量控制。
直接看接收方接收缓冲区的剩余大小。
如何把窗口大小告诉发送端?
在TCP的首部,有一个16位窗口字段,就是为了存放窗口大小信息。16位数字最大表示65535,那么TCP窗口的最大就是65535个字节么?
TCP首部40字节选项中还包含一个窗口扩大因子M,实际窗口大小是窗口字段的值左移M位。
3.3.6拥塞控制
流量控制【接收方的处理能力】+拥塞控制【传输过程中中间结点的处理能力 不好衡量,通过"实验"测试,逐渐找到一个合适的窗口大小】共同决定了发送方的窗口大小是多少【取较小值】。
拥塞窗口的值不是固定不变的,而是一直动态变化的。
先指数增长,之后线性增长之后回跳【热恋】
3.3.7延迟应答
如果接收数据的主机立刻返回ACK应答,这时候返回的窗口可能比较小。在接收方能够处理的了的前提下,尽可能的把窗口放大。
延迟:收到数据之后,不是立即返回ACK,而是稍微等会再返回。等待的时间里,接收方的应用程序,就能把接收缓冲区的数据消费一波,这样剩余空间就更大了
3.3.8稍带应答
也是提升效率的方式,在延迟应答的基础上,引入了捎带应答。
能够合并。
3.3.9面向字节流
粘包问题,明确两个包的边界:分隔符、长度。
3.3.10异常情况
出现了不可抗力的因素。
进程崩溃了
主机关机
进程没了,对应的PCB就没了,对应的问价描述符表就释放了,相当于socket.close();
此时内核会继续完成四次挥手,此时其实仍然是一个正常断开的流程。
主机关机要先杀进程,然后再正式关机(杀死进程的过程中,也是和上面一样触发四次挥手)
主机掉电
网线断开
假设是接收方掉电,发送方仍然再继续发送数据,发完数据要继续等待ACK,ACK等不到,超时重传,再怎么重传也收不到ACK,重传几次,还是没有应答,尝试重置tcp连接,(复位报文段 RST),显然这个重置也会时报,放弃连接。
如果是发送端掉电,接收方发现没有数据了,没数据是发送方挂了还是发送方要组织下语言重新发送接收方是不知道的,接收方选择先等,周期性的给发送方发送一个消息,确认下对方是否还正常工作。【心跳包--心跳是周期性的,如果心跳无了,就说明挂了,使用心跳包来确认通信双方是处在正常的工状态中】