目录
一.传输层
传输层是只有主机才有的层次,为应用层提供通信服务,并且能够使用网络层的服务。
传输层的功能:
**1.**传输层提供进程和进程之间的逻辑通信(网络层提供主机之间的逻辑通信)。
2. 复用和分用,复用 是指应用层所有的应用进程都可以通过传输层再传输到网络层,分用是指传输层从网络层收到数据后交付指明的应用进程。
如何区分不同的应用进程呢?这就需要用到端口号:
**端口(逻辑端口/软件端口)**是传输层的SAP,标识主机中的应用进程。
硬件端口和软件端口:硬件端口是一种实际的计算机的连接口,分为串行接口与并行接口,我们平常熟知的USB,SATA和IDE就是串行接口。而软件端口则仅仅是一个标识,标识不同的应用进程。
端口号只有本地意义,在因特网中不同计算机的相同端口是没有联系的。所以端口号只需要在本机内能唯一标识一个进程即可。
端口号长度为16bit,能表示65536个不同的端口号。
端口号按范围分:
非常重要的熟知端口号如下:
补充:套接字
在网络中采用发送方和接收方的套接字组合来识别端点(某个进程),套接字唯一标识了网络中的一个主机和它上面的一个进程。
套接字Socket=:(主机IP地址,端口号)
**3.**传输层对收到的报文进行差错检测。
**4.**传输层的两个协议:面向连接的传输控制协议TCP与无连接的用户数据报协议UDP
面向连接的传输控制协议TCP在传送数据之前必须建立连接,数据传送结束后要释放连接。不提供广播或多播服务。由于TCP要提供可靠的面向连接的传输服务,因此不可避免增加了许多开销:确认、流量控制、计时器及连接管理等。
**特点:**可靠,面向连接,时延大,适用于大文件。
无连接的用户数据报协议UDP传送数据之前不需要建立连接,收到UDP报文后也不需要给出任何确认。
**特点:**不可靠,无连接,时延小,适用于小文件。
二.UDP协议
UDP只在IP数据报服务之上增加了很少功能,即复用分用和差错检测功能。
1.UDP的特点:
1. UDP是无连接的,减少开销和发送数据之前的时延。
2. UDP使用最大努力交付,即不保证可靠交付 。可靠交付由传输层上的应用层保证。
3. UDP是面向报文的,适合一次性传输少量数据的网络应用。面向报文:
应用层的报文会作为应用层的传输单元往下传递,在传输层进行封装(封装上UDP首部)后继续往下传递,在网络层继续封装IP首部形成网络层传输单元。
面向报文就是:应用层给UDP多长的报文,UDP就照样发送,即一次发一个完整报文。所以应用层必须选择合适的大小的报文传递给传输层。
如果应用层报文过大 ,UDP一次发一个完整的报文给网络层,那么网络层就必须进行分片以满足链路层MTU(最大传送单元)的要求。这样就会降低网络层的效率。如果应用层的报文过小,传递到网络层后,IP首部的相对长度就会较大,这样也会降低网络层的效率。
**4.**UDP无拥塞控制,适合很多实时应用。
**5.**UDP首部开销小,8B,而TCP首部开销为20B。
2.UDP的首部格式:
16位的源端口号:源端口号是可有可无的,如果传送某数据需要收到回复,那么添加源端口号,这样对方才能知道将回复发给哪个进程。
**16位的目的端口号:**目的端口号是一定要有的,因为发送数据到某个主机的某个进程是一定要有指向的。
16位UDP长度:UDP用户数据报的整个长度(首部字段+数据字段)。
16位UDP检验和:检测整个UDP数据报是否有错,错就丢弃。分用时,找不到对应的目的端口号,就丢弃报文,并给发送方发送ICMP"端口不可达"差错报告报文。
3.UDP校验的过程:
UDP 校验和是一个端到端的传输层校验和,是对包含了IP头部中的源(Source)和目的IP地址(Destination Address)字段的UDP 伪首部计算得到的。
它由初始的发送方计算得到,由最终的目的方校验。它在传输中不会被修改(除非它通过一个NAT)。IPV4 头部中的校验和只覆盖整个头部 (即它不覆盖IP分组中的任何数据),它在每个IP跳都要被重新计算(因为IPV4 TTL字段的值在数据报转发时会被路由器减少)。**传输协议(如 TCP、UDP)使用校验和来覆盖它们的头部和数据。**对于 UDP 来说,校验和是可选的,而其他的则是强制的。当 UDP 在IPV6中使用时,校验和的计算与使用是强制的,因为在IP层没有头部校验和。为了给应用程序提供无差错数据,像UDP这样的传输层协议,在投递数据到接收方应用程序之前,必须计算校验和或者使用其他差错监测机制。
伪首部(模仿IP首部):
在UDP伪首部中,第1个字段是32位源IP地址;第2个字段是32位目的IP地址;第3字段是全零;第4字段是IP首部中的协议字段的值,对于UDP,此协议字段值为17(封装UDP报文的IP数据报首部协议字段是17);第5字段是UDP用户数据报的长度(包括UDP首部8B+数据部分长度**(不包括伪首部)**)。
因此,这样的检验和,既检查了UDP用户数据报的源端口和目的端口以及UDP用户数据报的数据部分,又检查了IP数据报的源IP地址和目的地址。
伪首部并非TCP&UDP数据报中实际的有效成分。伪首部是一个虚拟的数据结构,其中的信息是从数据报所在IP分组头的分组头中提取的 ,既不向下传送也不向上递交,而仅仅是为计算校验和。
伪首部的目的是让UDP层验证数据是否已经到达正确的目的地(即,该IP没有接受地址错误的数据报,也没有给UDP一个其他传输层协议的数据报),计算UDP校验和时覆盖的字段,包含了伪首部以及UDP头部和数据部分。
如何用伪首部校验UDP数据报是否发生差错:
如下图所示,每一行包含4B,用伪首部距离,第一行为源IP地址(4B),第二行为目的IP地址(4B),全零(1B),17(协议字段,1B),15(UDP数据报的总长度,2B),总共12B。
在发送端:
1.填上伪首部
2.全0填充检验和字段
3.全0填充数据部分(UDP数据报要看成许多4B的字串接起来)
4.伪首部+首部+数据部分采用二进制反码求和(即为先进行 二进制数 取反 ,然后求和)
5.把和求反码填入检验和字段(就是把和的"1"写成"0","0"写成"1")
6.因为已经计算完检验和,所以去掉伪首部,发送数据报。
在接收端:
1.填上伪首部
2.伪首部+首部+数据部分采用二进制反码求和(虽然和发送端的第4部一样),但是发送端的校验和字段是全0的,这里的校验和是刚刚计算得到的校验和。
3.结果全为1则无差错,否则丢弃数据报或者不丢弃,将数据报交给应用层附上出差错的警告,接下来的差错控制由应用层负责。
三.TCP协议
1.TCP协议的特点
•TCP是面向连接(虚连接)的传输层协议。
•每一条TCP连接只能有两个端点,两个端点之间只能进行一对一地通信,所以TCP协议不支持广播通信与组播通信这样一对多或多对多的通信。
•TCP提供可靠交付的服务,无差错、不丢失、不重复、按序到达。(可靠有序,不丢不重)
•TCP提供全双工通信,即发送方和接收方可以同时接收数据也可以同时发送数据,正是因为这样的机制,发送方和接收方都会设置两个缓存,即发送缓存和接收缓存。
发送缓存:包含准备发送的数据和已发送但尚未收到确认的数据。
接收缓存:包含按序到达但尚未被接受应用程序读取的数据和不按序到达的数据。
•TCP是面向字节流的,TCP把应用程序交下来的数据看成仅仅是一连串的无结构的字节流。
**"流"**指的是流入到进程或从进程流出的字节序列。
TCP会将传下来的数据按照字节排序并编上序号,当要发送文件时,就把数据放入到发送缓存中,并按照序号发送,如下图所示,首先以1,2,3字节(这里的字节是不定的,后面会继续说明)作为TCP的数据字段,再添加TCP头部,形成完整的报文段在链路上传输。
2.TCP报文段首部格式
报文首部格式如下图所示:
源端口和目的端口:表明源端口和目的端口,都是16位,总共32位
序号: 在一个TCP连接中传送的字节流中的每一个字节都按顺序编号,本字段表示本报文段所发送数据的第一个字节的序号。如下图所示的例子TCP首部的"序号"字段就是发送的第一个字节的序号,即1
确认号 :期望收到对方下一个报文段的第一个数据字节的序号。若确认号为N,则证明到序号N-1为止的所有数据都已正确收到。
数据偏移(首部长度) :TCP报文段的数据起始处距离TCP报文段的起始处有多远(首部长度),以4B为单位 ,即1个数值是4B。例如数据偏移由4位表示,最大为1111(15),所以"数据偏移"可以表示0~60个字节(15*4=60),也就是TCP最大长度为60个字节,其中20个字节为固定首部,40个字节为选项以及填充字段。
6位控制位:
紧急位URG:URG=1时,标明此报文段中有紧急数据,是高优先级的数据,应尽快传送,不用在缓存里排队,配合紧急指针字段使用。
确认位ACK:ACK=1时确认号才有效,在连接建立后所有传送的报文段都必须把ACK置为1。
推送位PSH:PSH=1时,接收方尽快交付接收的应用进程,不再等到缓存填满再向上交付。
复位RST:RST=1时,表明TCP连接中出现严重差错,必须释放连接,然后再重新建立传输链接。也可以用来拒绝非法的报文段或连接请求。
同步位SYN:SYN=1时,表明是一个连接请求/连接接受报文。只有在连接请求或连接接收这两个情况下,SYN才置为1。
终止位FIN:FIN=1时,表明此报文段发送方数据已发完,要求释放连接。
窗口 :指的是发送本报文段的一方的接收窗口,即现在允许对方发送的数据量。发送方就可以通过接收方发来的TCP首部的"窗口"字段来设置自己发送窗口的大小。
例如接收方给发送方发送的"确认号"=701,窗口大小为1000个字节,翻译过来就是"701之前的数据我已全部正确接收,期待接收序号为701的字节,并且我现在的窗口大小为1000",那么接收方的接收缓存空间就是701~1700。
检验和:检验首部+数据,检验时要加上12B伪首部,第四个字段(协议字段)为6(UDP中的协议字段为17)。
**紧急指针:**URG=1时才有意义,指出本报文段中紧急数据的位置以及字节数。
**选项:**最大报文段长度MSS、窗口扩大、时间戳、选择确认.....最开始TCP规定的选项只有最大报文长度MSS,即TCP报文段中数据部分的长度,随着因特网发展,又陆续增加了其他选项字段。
填充:如果"选项"字段不是4个字节的整数倍,那么就需要"填充"字段填充"0",使得整个TCP首部长度为4字节的整数倍。
3.TCP的连接管理
TCP连接需要经历3个阶段:
(1)连接建立(三次握手)
TCP连接的建立采用客户服务器方式,主动发起连接建立的应用进程叫做客户,而被动等待连接建立的应用进程叫服务器。假设运行在一台主机(客户)上的一个进程想与另一台主机(服务器)上的一个进程建立一条连接,客户应用进程首先通知客户TCP,他想建立一个与服务器上某个进程之间的连接,客户中的TCP会用以下步骤与服务器中的TCP建立一条TCP连接:
1. 客户端发送连接请求报文段,无应用层数据。
SYN=1,seq=x(随机)
2. 服务器端为该TCP连接分配缓存和变量 ,并向客户端返回确认报文段,允许连接,无应用层数据。
SYN=1,ACK=1,seq=y(随机),ack=x+1
3. 客户端为该TCP连接分配缓存和变量,并向服务器端返回确认的确认,可以携带数据。
SYN=0,ACK=1,seq=x+1, ack=y+1
SYN洪泛攻击:
SYN洪泛攻击发生在OSI第四层,这种方式利用TCP协议的特性,就是三次握手。攻击者发送TCP SYN,SYN是TCP三次握手中的第一个数据包 ,而当服务器返回ACK后,该攻击者就不对其进行再确认,那这个TCP连接就处于挂起状态,也就是所谓的半连接状态,服务器收不到再确认的话,还会重复发送ACK给攻击者。这样更加会浪费服务器的资源。攻击者就对服务器发送非常大量的这种TCP连接,由于每一个都没法完成三次握手,所以在服务器上,这些TCP连接会因为挂起状态而消耗CPU和内存,最后服务器可能死机,就无法正常为用户提供服务了。
(2)连接释放(四次握手)
参与一条TCP连接的两个进程中的任何一个都能终止该连接,连接结束后,主机中的"资源"(缓存和变量)将被释放。
1. 客户端发送连接释放报文段 ,停止发送数据,主动关闭TCP连接。
FIN=1,seq=u
**2.**服务器端回送一个确认报文段,客户到服务器这个方向的连接就释放了---半关闭状态。
ACK=1,seq=v, ack=u+1
**注:**这里的"seq"取决于服务端之前发送到哪里,例如服务器上一个发送的报文段的最后一个字节是v-1,那么这里的seq就应该等于v。
**3.**服务器端发完数据,就发出连接释放报文段,主动关闭TCP连接。
FIN=1,ACK=1,seq=w,ack=u+1
**注:**因为客户在2,3步之间没有发送数据,所以他们期待的下一个报文段一定是相同的。
4. 客户端回送一个确认报文段,再等到时间等待计时器设置的2**MSL(最长报文段寿命)**后,连接彻底关闭。
ACK=1,seq=u+1,ack=w+1
如果客户端发送的确认报文段最后没有到达服务器端(丢失),服务端就会重传第(3)个报文段,也就是连接释放的报文段,那么客户端会在2MSL之内收到服务端重传的连接释放的报文段,并重新发送确认报文段。
如果没有这样的"等待时间",服务器端就会一直发连接释放的报文段,没办法进入正常关闭状态。
4.TCP的可靠传输
因为网络层采用的是尽最大努力交付,即不可靠的传输方式,所以网络层的上一层就需要担负起可靠传输的职责。传输层的TCP就能够实现可靠传输(UDP也是不可靠的传输,如果采用UDP协议,那么可靠传输就靠应用层来完成)。
可靠是什么呢?
即保证接收方进程从缓存区读出的字节流与发送方发出的字节流是完全一样的。
TCP的可靠传输机制有以下4种:
(1)校验
与UDP校验一样,增加伪首部,通过二进制反码求和的方法判断报文段是否有错。
(2)序号
一个字节占用一个字段,一个报文段首部的"序号"字段标明的就是一个报文段第一个字节的序号。
基于产生了"确认"和"重传"机制:
(3)确认
如下图所示,发送方发送第一个报文段给接受方,接收方收到这一报文段后会存储在缓存中,并且在适合的时候上交给应用层,此时发送方的缓存中还是保留着第一个报文段,这是因为如果这一报文段在传输过程中丢失,接收方收不到这一报文段,就会让发送方再次发送这个报文,接收方如何通知发送方是否接收到正确完整的报文段呢?这就需要用到确认机制,即接收方收到正确报文段后,给发送方回复确认报文,通常采用累积确认 的方式。接收方可以在发送数据的时候捎带这一确认报文(捎带确认)。
如果接收方发送的确认报文段序号为4,就是告诉发送方序号4之前的报文段我已正确接收,接下来期待接收到序号为4的报文段,这时候1,2,3字节的报文段就能删去了。
假设现在发送方陆续发送4,5,6报文段以及7,8报文段,但是4,5,6报文段在发送过程中丢失了,7,8报文段被正确接收。这时接收方返回的确认报文首部的"确认"字段还是4,也就是只确认数据流当中**至第一个丢失字节为止的字节(累计确认)。**所以接收方会正确接收7,8报文段,并且告诉发送方期待收到序号为4的字节开头的报文段。
发送方收到这样的确认报文后,会重传 序号为4的字节开头的报文段,接收方正确接收后,4,5,6,7,8字节都正确接收了,那么就会发送**"确认"字段**为9的确认报文,告诉发送方期待接收序号为9的字节。
(4)重传
•超时重传
TCP的发送方在规定的时间内没有收到确认就要重传已发送的报文段(超时重传)。
重传时间的规定较为复杂,由于TCP的下层是一个互联网的环境,发送的报文段可能是一个高速的局域网或者多个低速的局域网,并且每个IP数据报所选择的路由不同,这取决于当时的网络情况,所以这就导致发送方发送的报文段所走路径不同,花费的时间不同。
重传时间过短,会引起很多报文段不必要的重传,有的报文段传输的时间较长,如果设置的重传时间过短,就会导致这些报文段还没有到达接收方就被重传,这会大大增加网络负荷。
重传时间过长,又会使网络空闲时间较多,降低网络效能。
那么传输层应该如何设置重传时间呢(如何设置超时计时器的时间)?
TCP采用自适应算法 ,动态改变重传时间(加权平均往返时间),RTT指的是从报文段发送开始到收到确认报文的时间。例如,在发送第一个报文时,采用的就是从报文段发送开始到收到确认报文的时间。当发送第二个报文段时,他会结合第一个报文段的计算得到新的作为现在的重传时间,以此类推。这样重传时间是取决于每个报文段的RTT的。
有没有一种办法,能在超时事件发生之前就让发送方知道有没有丢失报文段,然后尽快重传:
•冗余确认
冗余ACK(冗余确认):
每当比期望序号大的失序报文段到达时,发送一个冗余ACK,指明下一个期待字节的序号。例如:
1.发送方已发送1,2,3,4,5报文段。
2.接收方收到1,返回给1的确认(确认号为2的第一个字节)
3. 接收方收到3,仍返回给1的确认(确认号为2的第一个字节)
所以如果发生了失序接收 的情况,那么返回的确认号是失序前正确的字节的序号
4. 接收方收到4,仍返回给1的确认(确认号为2的第一个字节)
5. 接收方收到5,仍返回给1的确认(确认号为2的第一个字节)
发送方收到3个对于报文段1的冗余ACK,就会认为2报文段丢失,并且重传2号报文段。 这种技术也叫**"快速重传机制"。**
注意 :TCP的接收窗口,发送窗口以及在发送报文段过程中使用协议(停等协议,GBN协议以及SR协议)和数据链路层是一样的(在数据链路层章节讲过)。
TCP协议的可靠传输并不是一个比较重要的考点,我们主要掌握的是TCP的拥塞控制和流量控制,所以这里就不再细讲这些内容了。
5.TCP的流量控制与拥塞控制
对于TCP的流量控制和拥塞控制我之前已经总结过: