活动发起人@小虚竹 想对你说:
这是一个以写作博客为目的的创作活动,旨在鼓励大学生博主们挖掘自己的创作潜能,展现自己的写作才华。如果你是一位热爱写作的、想要展现自己创作才华的小伙伴,那么,快来参加吧!我们一起发掘写作的魅力,书写出属于我们的故事。我们诚挚邀请你参加为期14天的创作挑战赛!
提醒:在发布作品前,请将不需要的内容删除。
1.应用层
我们之前编写完了基本的 java socket ,要知道,我们之前所写的所有代码都在应⽤层,都是为了 完成某项业务,如翻译等。关于应⽤层,我们在讲解完毕基本的 TCP/IP 协议之后,我们会单独来进 ⾏讲解。
2.传输层
负责数据能够从发送到传输到接收端。
2.1 再谈端口号
端口号标识了一个主机上进行通信的不同的应用程序。
在TCP/IP协议中,⽤"源IP","源端⼝号","⽬的IP","⽬的端⼝号","协议号"这样⼀个五元组来标识⼀个 通信(可以通过netstat-n查看);
端⼝号范围划分
• 0-1023:知名端⼝号,HTTP,FTP,SSH等这些⼴为使⽤的应⽤层协议,他们的端⼝号都是固定的.
• 1024-65535:操作系统动态分配的端⼝号.客⼾端程序的端⼝号,就是由操作系统从这个范围分配 的.
2.2UDP协议
UDP协议格式
• 16位UDP⻓度,表⽰整个数据报(UDP⾸部+UDP数据)的最⼤⻓度; 如果校验和出错,就会直接丢弃;
UDP的特点:
- 无连接:知道对端的IP和端⼝号就直接进⾏传输,不需要建⽴连接,
- 不可靠传输:没有确认机制,没有重传机制;如果因为⽹络故障该段⽆法发到对⽅,UDP协议层也不会给应 ⽤层返回任何错误信息;(如何理解这里的不可靠,⾯向数据报 应⽤层交给UDP多⻓的报⽂,UDP原样发送,既不会拆分,也不会合并;)
- 面向数据报:不能够灵活的控制读写数据的次数和数量
- 全双工
我们接下来了解UDP报头,我们所熟知的HTTP协议的报头是文本格式的,UDP/TCP/IP的报头是二进制格式的。
长度
整个UDP数据报长度(报头+载荷),长度属性也是两个字节,表示范围0~65535(64KB).
端口号
一个端口号的取值范围是0~65535,实际上一般把1024以下的端口保留,我们写代码都用1024~65535这个范围的。服务器的端口是程序员指定的(提前指定好,客户端才能访问到),客户端的端口是系统自动分配的空闲端口(如果提前指定了,可能会与你客户端上的程序起冲突)。
校验和
验证数据是否发生修改,之前我们将HTTP的数字签名是为了防止黑客篡改(防人),但UDP的校验和不是为了防人,和安全性无关,而是为了防止出现运输过程中的“比特翻转”(即1变0,0变1)。
发送之前,先计算一个校验和,把整个数据包的数据都代入,把数据与校验和一起发送给对端,接收方收到之后重新计算一下校验和,和收到的校验和进行对比(UDP发现校验和不一致,就会直接丢弃)。UDP的校验和使用了CRC方式来进行校验(循环冗余校验),把每个字节(除了校验和位置的部分之外),都当做整数,进行累加,溢出来也没有关系,继续加最终得到结果,crc校验和传输到对端,数据出现错误了,对端再次 计算的校验和就会和第一个校验和不以样。
认为两个原始数据相同,使用相同的校验和算法,得到的校验和也应该是相同的,反之,两个校验和相同,原始数据一定也相同(可能存在变数)。
UDP使⽤注意事项
UDP总长度最大是64KB,可以表述为UDP总长度达到64KB或UDP携带的载荷长度达到64KB上限。
我们注意到,UDP协议⾸部中有⼀个16位的最⼤⻓度.也就是说⼀个UDP能传输的数据最⼤⻓度是 64K(包含UDP⾸部). 然⽽64K在当今的互联⽹环境下,是⼀个⾮常⼩的数字.如果我们需要传输的数据超过64K,就需要在应⽤层⼿动的分包,多次发送,并在接收端⼿动拼装。
2.3TCP协议
TCP协议特点:有链接,面向字节流,可靠传输,全双工。
TCP协议段格式
1.16位源端口号/16位目的端口号:传输层的核心内容;
2.4位首部长度:表⽰该TCP头部有多少个32位bit(有多少个4字节);所以TCP头部最⼤⻓度是15* 4=60。
3.选项:选项的存在,导致tcp报头长度是可变的。
4.保留6位:TCP报头中就预留了一些“保留位”,现在先不用,但是先占个位子。
5.:TCP最核心的6个标志位
- URG:紧急指针是否有效.
- ACK:确认号是否有效,ack为1,表示是应答报文.
- PSH:提⽰接收端应⽤程序⽴刻从TCP缓冲区把数据读⾛.
- RST:对⽅要求重新建⽴连接;我们把携带RST标识的称为复位报⽂段.
- SYN:请求建⽴连接;我们把携带SYN标识的称为同步报⽂段.
- FIN:通知对⽅,本端要关闭了,我们称携带FIN标识的为结束报⽂段.
6.16位校验和:用来校验数据是否出现错误.
7.针对确认应答中的情况,给数据进行编号,其中确认序号只在应答报文中才生效。
8.16位紧急指针:标识哪部分数据是紧急数据
TCP的核心机制
可靠性:此处的可靠性,不是说A给B发一个消息,B100%能收到,而是A给B发了消息之后,尽量让B收到消息。
TCP核心机制一:确认应答
保证可靠性的一个关键前提,发送方知道自己的数据是否被对方收到,需要对方给返回一个“应答报文”(acknowledge.ack),发送方知道应答报文,就可以确认对方收到了。
举个例子,我们用短信给别人发送多条消息时,正常情况下,如图所示
但是在网络上会出现后发先至的情况,如图所示,这种情况会引起误解,
那么针对这种情况,我们又该如何解决,接下来我们介绍一下TCP的解决方案
TCP将每个字节的数据都进行了编号,即为序列号。上述列子编号如上图所示:
每⼀个ACK都带有对应的确认序列号,意思是告诉发送者,我已经收到了哪些数据;下⼀次你从哪⾥开始 发.
1.TCP是面向字节流的,在编号时,不是按照用条、2条来编号的,而是按照“字节”的方式来编号的,每个字节都分配一个编号,编号是连续递增的。
一个TCP的载荷是由多个字节构成的,需要多个编号,那么此处的序号该怎么填写:序号字段填写载荷部分的第一个字节的序号,序号连续递增;确认序号填法是把收到的载荷数据的最后一个字节序号+1。
2.引入序号之后,接收方就可以根据序号对数据进行排序,TCP需要先处理后发先至的情况,确保应用程序通过socket api读到的数据顺序(即确保代码里读到的数据和发送方写入的数据顺序一致)是正确的。
3.TCP报头不参与排序,序号、确认序号都是针对载荷的,TCP在接收方这里会安排“接收缓冲区”,(内存,操作系统内核里),通过网卡读到的数据,先放到缓冲区中,后续代码里调用read,也是从接收缓冲区来读的。
4.在接收缓 冲中,根据序号来排序,序号小的在前面,大的在后面,确保前面的数据已经到了,然后read才能接触阻塞,如果是后面的数据先到,read会继续阻塞,不会读取到数据。
TCP核心机制二:超时重传
1.超时重传是针对丢包的情况做出处理,这里首先会设置一个超时时间,
比如A给B发送数据等B的回应,如果达到等待时间上限,还没有收到ack,A就认为传输过程中发生丢包情况。这里的丢包可能是A给B发生的数据丢了或者B给A返回的ack丢了。
2.为什么会发生丢包现象?
因为网络结构是非常复杂的,数据报经过某个路由器,交换机转发的时候,该路由器、交换机已经非常繁忙了,导致当前所需要转发的数据量超出路由器、交换机的转发能力上限,此时,数据报会消耗更多的时间,才能到达对方,跟糟糕的是,数据报太多,路由器、交换机根本处理不过来,接收缓冲区已满,只能丢弃。
3.丢包是不能避免的客观现象,而重传是有效对抗丢包的手段。
4.如何判断是否丢包?
引入超时时间来判断是否丢包,TCP中,判断超时时间的阈值,不是固定数值,是动态改变的。
假设当前A向B发送数据,丢包时间的阈值是T,当A给B传输发生超时之后,就会延长这个时间阈值,即延长这个时间,但不是无休止的,超时次数达到一定程度或等待时间达到一定程度,就会认为网络出现严重故障,放弃这一次传输。
5.针对A给B发生的数据丢了或者B给A返回的ack丢了这两种情况,发送方A区分不了当前是那种情况,所有都重传。
情况1
A给B发生的数据丢了,直接重传就可以了。
情况2
对于这种情况,B已经收到了一份数据,如果重传,B就会收到两份一样的数据,如果tcp不处理,可能会使应用层读到两次一样的数据,所以tcp会在内部进行去重操作,此时根据序号,在接收缓冲区中寻找,如果存在,就直接丢弃;如果不存在,才放进去。
注:确认应当和超时重传是TCP最核心的两个机制,保证了TCP能够进行可靠运输。