3.1 概述和运输层服务
应用层-运输层-网络层
运输层协议为运行在不同主机上的应用进程之间提供了逻辑通信功能。
协议在端系统中而不是在路由器中实现,网络路由器仅作用于该数据报的网络层字段,即它们不检查封装在该数据报的运输层报文段的字段。
注:网络层提供了主机之间的逻辑通信,而运输层为运行在不同主机上的进程之间提供逻辑通信
*运输层协议只工作在端系统中
UDP用户数据报协议
TCP传输控制协议
报文段
网络层—IP网际协议
服务模型:尽力而为模型
提供不可靠服务
最低限度的运输层服务:进程到进程间的数据交付和差错检验(这也是UDP所能提供的仅有的两种服务)
TCP提供的附加服务:可靠数据传输(流量控制、序号、定时器) 拥塞控制
3.2多路复用和多路分解
应用层报文 -> 运输层报文段 -> 网络层数据报 -> 链路层帧
多路复用和多路分解:
也就是将由网络层提供的主机到主机交付服务延伸到为运行在主机上的应用程序提供进程到进程的交付服务。
每个运输层报文端中具有几个字段,在接收端,运输层检查这些字段,标识出接收套接字,进而将报文段定向到该套接字。将运输层报文端中的数据交付到正确的套接字的工作叫做多路分解。分解入
在源主机从不同套接字中收集数据块,并为每个数据块封装上首部信息从而生成报文段,然后将报文段传递到网络层的工作叫做多路复用。统一出
多路复用要求:
1、套接字有唯一标识符;
2、每个报文段有特殊字段来指示该报文段所要交付到的套接字。
(特殊字段包括源端口号字段和目的端口号字段等,端口号是一个16比特的数,其大小在0~65535之间,其中0~1023范围的端口号称为周知端口号,是受限制的)
- 无连接的多路复用和多路分解 : 通常应用程序的客户端让运输层自动地分配端口号,而服务器端则分配一个特定的端口号。一个UDP套接字由一个二元组来全面标识,二元组包含一个目的IP地址和一个目的端口号。因此,如果两个UDP报文段有不同的源IP地址和/或源端口号,但有相同的目的IP地址和目的端口号,那么这两个报文段将通过相同的目的套接字被定向到相同的目的进程。源端口号的作用是用在返回地址中,做为返回的报文的目的端口号。
- 面向连接的多路复用和多路分解 : TCP有套接字是由一个四元组(源IP地址,源端口号,目的IP地址,目的端口号)来标识的。所以两个具有不同源IP地址或源端口号的到达TCP报文段将被定向到两个不同的套接字。
nmap 端口扫描器
目前的Web服务器:使用一个进程—有新连接上来—>创建一个具有新连接套接字的新线程
3.3无连接运输:UDP
UDP只是做了运输协议能够做的最少工作,除了复用/分解功能以及少量的差错检验外,它几乎没有对IP增加别的东西。DNS是一个通常使用UDP的应用层协议的例子。
UDP的优势:1、关于何时,发送什么数据的应用层控制更为精细。2、无需连接建立。3、无连接状态。4、分组首部开销小。UDP报文段是32bit,8个字节
注:使用UDP的应用是可以实现可靠数据传输的,比如通过在应用程序自身中建立可靠性机制。这样,应用程序可以进行可靠性通信,而无需受制于由TCP拥塞控制机制。
UDP检验和:UDP检验和提供了差错检测功能,也就是说,检验和用于确定当UDP报文段从源到达目的地移动时,其中的比特是否发生了改变。
UDP提供检验和的原因是由于不能保证源和目的地之间的所以链路都提供差错检测。在既无法确保逐链路的可靠性,又无法确保内存中的差错检测的情况下,UDP就必须在端到端基础上在运输层提供差错检测。这个设计被叫做端到端原则。虽然UDP提供差错检测,但它对差错恢复无能为力,它只是丢弃受损的报文段。
3.4 可靠数据运输原理
可靠数据传输包括差错检测,重传,累积确认,定时器以及用于序号和确认号的首部字段等等。
rdt1.0
rdt2.0
加上了自动重传请求协议 ARQ。ACK+NAK
停等机制
rdt2.1
担心ACK或NAK本身传的有问题,因为停等机制,就不会再发数据了。
—>分组加上序号,确定收到的分组是否是重传
rdt2.2 无NAK的可靠数据传输协议
rdt 3.0 具有波特差错的丢包信道上,如何实现可靠数据传输?
rdt 3.0也被称之为比特交替协议
冗余数据分组
重传是一个灵丹妙药
3.4.2 流水线可靠数据传输协议
如何实现差错恢复呢?::
3.4.3回退N步GBN
3.4.4选择重传SR
分组重新排序?
3.5面向连接的运输TCP
应用层报文 -> 运输层报文段 -> 网络层数据报 -> 链路层帧
面向连接的,其连接状态全部保留在两个端系统中,中间的网络元素(如路由器)对TCP完全是视而不见的
全双工、点到点
多播:一个发送方,将数据发送为多个接收方
MSS 最大报文段长度—>报文段里面,应用层数据的最大长度,不包含TCP首部!
根据路径MTU,设置MSS
TCP连接
- 建立连接之后,主机间通过套接字传递数据流:数据一但进入套接字,就由运输层控制了,TCP将这些数据引导至发送缓存,并不时从里面取出一块数据,配上TCP首部行,形成TCP报文段,然后向下传递给网络层;
- 当另一端的TCP接收到一个报文段后,就将数据存放在TCP的接收缓存中,应用程序从此接收缓存中读取数据流。
- (需要注意的是主机之间的网络元素没有为该TCP链接分配任何缓存和变量)。
TCP报文段
TCP的首部行一般是是20字节(UDP的首部行是8个字节)。与UDP一样,TCP报文端首部行包括源端口号,目的端口号以及检验和字段。
序号和确认号
TCP提供 累积确认,TCP只确认该流中至第一个丢失字节为止的字节
接受窗口字段,用于流量控制
6Bit的标志字段,里面有六个标志 ACK SYN FIN 等
基于Telnet来学习序号和确认号
确认号,主机正在等待的数据的下一个字节序列
3.5.4可靠数据传输
TCP的可靠数据传输确保一个进程从其接收缓存中读出的数据流是无损坏,无间隔,非冗余和按序的数据流,从TCP的发送方高度简化的角度来看,需要监控三个事件:运输层从上层应用接收数据,定时器超时和收到ACK
- 第一个事件发生,TCP将接收到数据封装成报文段,每个报文段都包含一个序号。另外,如果此时定时器如果没有为其他某些报文段运行,则将数据传递给IP层时,TCP会启动该定时器(定时器与最早的未被确认的报文段相关联)。
- 如果触发了超时事件,则TCP会重传引发超时事件的那个报文段,并重启定时器
- TCP维护一个状态变量sendbase,是最早未被确认的字节的序号。当TCP接收到来自接收方的ACK响应后,会将ACK的值y与sendbase进行比较,TCP采用的是累积确认,即y确认了字节编号在y之前的所有字节都已经接收到了。如果y > sendbase,则发送方更新sendbase。
3.5.5流量控制
流量控制 发送方太快,接受方缓存不够用—>遏制发送方
拥塞控制 放送路上的网络堵塞—>遏制发送方
接收窗口
rwnd(缓存可用空间) = 接收缓存总大小 - 缓存中已经存在的TCP数据
UDP不提供流量控制,可能存在缓存溢出的情况
TCP的特点之一是提供体积可变的滑动窗口机制,支持端到端的流量控制。TCP的窗口以字节为单位进行调整,以适应接收方的处理能力。处理过程如下:
(1)TCP连接阶段,双方协商窗口尺寸,同时接收方预留数据缓存区;
(2)发送方根据协商的结果,发送符合窗口尺寸的数据字节流,并等待对方的确认;
(3)发送方根据确认信息,改变窗口的尺寸,增加或者减少发送未得到确认的字节流中的字节数。调整过程包括:如果出现发送拥塞,发送窗口缩小为原来的一半,同时将超时重传的时间间隔扩大一倍。
TCP的窗口机制和确认保证了数据传输的可靠性和流量控制。
TCP/IP滑动窗口
3.5.6TCP连接管理
三次握手
四次挥手
SYN 只在握手中出现
FIN 只在挥手中出现
SYN洪泛攻击
SYN Cookie 防御系统
3.6 拥塞控制原理
遏制发送方,来处理网络拥塞
1、拥塞原因及其代价
2、拥塞控制方法
3、例子:网络辅助的
拥塞控制
【问题1】为什么连接的时候是三次握手,关闭的时候却是四次握手?
答:因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,”你发的FIN报文我收到了”。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手。
为什么TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回到CLOSE状态?
答:虽然按道理,四个报文都发送完毕,我们可以直接进入CLOSE状态了,但是我们必须假象网络是不可靠的,有可以最后一个ACK丢失。所以TIME_WAIT状态就是用来重发可能丢失的ACK报文。
MSL是Maximum Segment Lifetime,最大报文段生存时间,2个MSL是报文段发送和接收的最长时间。、
TCP三次握手与四次挥手最简洁易懂的解释
TCP的三次握手和四次挥手
关闭连接的四次握手里面如果第三次如果一直不发FIN会怎么处理?
如果客户端是主动关闭端的话,服务端忘记处理在read==0后关闭连接,就会造成不发送FIN分节(可以在三次握手后修改服务端的iptable drop掉FIN分节,这样服务端就再也不会收到来自客户端的FIN分节了):
此时客户端陷在TIME_WAIT_2,服务端陷在CLOSE_WAIT,不谈客户端,服务端陷入CLOSE_WAIT会一直占着文件描述符,
简单粗暴点就重启一下进程,要么就根据不同场景修改timeout的大小(我个人觉得减小timeout就行了,timeout一到直接发个RST了事)