- 运输层位于应用层与网络层之间,是分层的网络体系结构的重要部分。该层为运行在不同主机上的应用进程提供直接的通信服务起着至关重要的作用。
概述和运输层服务
- 运输层协议为运行在不同主机上的应用进程之间提供了逻辑通信(logic communication)功能。
- 从应用程序的角度看,通过逻辑通信,运行不同进程的主机好像直接相连一样。
- 运输层协议是在端系统中而不是在路由器中实现的。
- 在发送端,运输层将从发送应用程序进程接收到的报文转换成运输层分组,用因特网属于来讲该分组成为运输层报文段。
运输层与网络层的关系
- 网络层提供了主机之间的逻辑通信,而运输层为运行在不同主机上的进程之间提供了逻辑通信。
因特网运输层概述
- 因特网为应用层提供了两种截然不同的可用运输层协议。
- 一种是UDP(用户数据报协议),它为调用它的应用程序提供了一种不可靠、无连接的服务。
- 另一种是TCP(传输控制协议),它为调用它的应用程序提供了一种可靠的、面向连接的服务。
- 运输层分组称为报文段
- TCP为应用程序提供几种附加服务:可靠数据传输,通过使用流量控制、序号、确认和定时器,TCP确保正确地、按序地将数据从发送进程交付给接收进程;拥塞控制。
- UDP流量是不可调节的,使用UDP传输的应用程序可以根据其需要以其愿意的任意速率发送数据。
多路复用与多路分解
- 在源主机从不同套接字中收集数据块,并为每个数据块封装上首部信息从而生成报文段,然后将报文段传递到网络层,所有这些工作称为多路复用。(多合一?)
- 将传输层报文段中的数据交付到正确的套接字的工作称为多路分解。(一分多?)
- 也就是统一收集,一起运输,然后分发
- 运输层多路复用要求:
- 套接字有唯一标识符
- 每个报文段有特殊字段来指示该报文段所要交付到的套接字
- 这些特殊的字段是源端口字段和目的端口字段。
- 端口号是一个16位的数,范围是0~65535之间
- 0~1023范围的端口号称为周知端口号,是受限制的,不能随便使用。比如,HTTP使用端口号80,FTP使用端口号21
- 当报文段到达主机时,运输层检查报文段中的目的端口号,并将其定向到相应的套接字。
无连接的多路复用与多路分解
- 通过UDP套接字分配端口号,我们现在能够精确地描述UDP的复用和分解了。
- 假定主机A具有一个UDP端口19157,它要发送一个应用程序数据块给位于主机B的另一个进程,该进程具有UDP端口号46428。
- 主机A中的运输层创建一个运输层报文段,其中包括应用程序数据、源端口号(19157)、目的端口号(46428)和两个其他值。
- 接收主机运输层就检查该报文段中的目的端口号(46428)并将该报文段交付给端口号46428所标识的套接字。
- 一个UDP套接字由一个二元组来全面标识,该组包含一个目的IP地址和一个目的端口号。
- 当B需要回发一个报文段给A时,B到A的报文段中的目的端口号便从A到B的报文段中的源端口号中取值。
面向连接的多路复用和多路分解
- TCP套接字和UDP套接字之间的一个细微差别是,TCP套接字是由一个四元组(源IP地址、源端口号、目的IP地址、目的端口号)来标识的。(因为TCP是有连接的,源端和目的端之间一一对应)
- 当一个TCP报文段从网络到达一台主机时,该主机使用全部4个值来将报文段定向(分解)到相应的套接字。
- 与UDP不同的是,两个具有不同源IP地址或源端口号的到达TCP报文段将被定向到两个不同的套接字,除非TCP报文段携带了初始创建连接的请求。
web服务器与TCP
- 在一个端口80上运行一个Apache Web服务器,当客户(如浏览器)向该服务器发送报文段时,所有报文段的目的端口都将为80。但是由于源IP和源端口号不一样,还是能进行区分。针对不同的源,会用不同的套接字进行接收。
- 连接套接字与进程之间并非总是有着一一对应的关系。事实上,当今的高性能Web服务器通常只使用一个进程,但是为每个新客户连接创建一个具有新连接套接字的新线程。
- 如果客户与服务器使用持续HTTP,则在整条连接持续期间,客户与服务器之间经由同一个服务器套接字交换HTTP报文。
- 然而,如果客户与服务器使用非持续HTTP,则对每一对请求/响应都创建一个新的TCP连接并在随后关闭。这种套接字频繁创建和关闭会严重影响一个繁忙的web服务器的性能。
无连接传输:UDP
-
UDP从应用进程得到数据,附加上用于多路复用/分解服务的源和目的端口号字段,以及两个其他的小字段,然后将形成的报文段交给网络层。
-
使用UDP时,在发送报文段前,发送方和接收方的运输层实体之间并没有握手。正因如此,UDP被称为时无连接的。
-
有许多应用更适合用UDP,原因如下:
- 关于何时、发送什么数据的应用层控制更为精确。对于一些实时应用,要求最小发送速率,不希望过分地延迟报文段的传送,并且能够容忍一些数据丢失,这些使用UDP会比较合适。
- 无需连接建立。不会引入建立连接的延时。
- 无连接状态。无需维护连接状态。TCP需要维护包括接收和发送缓存、拥塞控制参数以及序号与确认号的参数参数等。
- 分组首部开销小。TCP报文段都有20字节的首部开销,UDP仅有8字节的开销。
-
常用应用下面的运输协议
应用 应用层协议 下面的运输协议 电子邮件 SMTP TCP 远程终端访问 Telnet TCP Web HTTP TCP 文件传输 FTP TCP 远程文件服务器 NFS 通常UDP 流式多媒体 通常专用 UDP或TCP 因特网电话 通常专用 UDP或TCP 网络管理 SNMP 通常UDP 路由选择协议 RIP 通常UDP 名字转换 DNS 通常UDP -
使用UDP的应用是可以实现可靠数据传输的。这可通过在应用程序自身中建立可靠性机制来完成。例如可通过增加确认与重传机制来实现。
UDP报文段结构
![](https://i-blog.csdnimg.cn/blog_migrate/af94d2016fc6ac3a88fffc9be70775bb.png)
- UDP首部只有4个字段,每个字段由两个字节组成。通过端口号可以使目的主机将应用数据交给运行在目的端系统中的相应进程。
- 长度字段只是了在UDP报文段中的字节数
- 接收方使用检验和来检查在该报文段中是否出现了差错。
UDP检验和
- UDP检验和提供了差错检测功能。检验和用于确定当UDP报文段从源到达目的地移动时,其中的比特是否发生了改变。
可靠数据传输原理
- 为上层实体提供的服务抽象是:数据可以通过一条可靠的信道进行传输。实现这种服务的抽象是可靠数据传输协议(reliable data transfer protocol,rdt)的责任
- 通过调用
rdt_send()
函数,可以调用数据传输协议的发送方。它将要发送的数据交付给位于接收方的较高层 - 在接收端,当分组从信道的接收端到达时,将调用
rdt_rev()
。当rdt
协议想要向较高层交付数据时,通过deliver_data()
来完成。
构造可靠传输协议
经完全可靠信道的可靠数据传输:rdt1.0
- 有限状态机,Finite-State Machine, FSM
- 箭头指示了从一个状态转到另一个状态,虚线表示初始状态
- rdt的发送端只通过rdt_send(data)事件接收来自较高层的数据,产生一个包含该数据的分组(经由make_pkt(data)动作),并将分组发送到信道中。
- 在接收端,rdt通过rdt_rcv(packet)事件从底层信道接收一个分组,从分组中取出数据(通过extract(packet, data)),并将数据上传给较高层(通过deliver_data(data))。
- 假定接收方接收数据的速率和发送方发送数据的速率一样快
经具有比特差错信道的可靠数据传输:rdt2.0
- 采用了肯定确认(positive acknowledgment)也就是“ok”,否定确认(negative acknowledgment)也就是“请重复一遍”。
- 这种控制报文使得接收方可以让发送方知道哪些内容被正确接收,哪些内容接收有误并因此需要重复。
- 基于这样重传机制的可靠数据传输协议称为自动重传请求协议(Automatic Repeat reQuest,ARQ)协议
- ARQ协议还需要另外三种协议功能来处理存在比特差错的情况
- 差错检测。检测何时出现了比特差错。
- 接收方反馈。接收方需要给发送方发送确认,肯定确认(ACK)和否定确认(NAK)。
- 重传。接收方收到有差错的分组时,发送方将重传该分组文。
- 有限状态机
- 发送端两个状态。
- 在左边的状态中,等待上层传下来数据。当有数据传下来之后,通过
rdt_send(data)
产生一个包含待发送数据的分组,然后经由udt_send(sndpkt)
操作发送该分组。 - 在最右边的状态,发送方协议等待接收方的ACK或NAK分组。如果收到ACK,就返回左边的状态;如果收到NAK,就重传。
- 在左边的状态中,等待上层传下来数据。当有数据传下来之后,通过
- 当处于右边状态的时候,不能接收上层传过来的数据,因此rdt2.0协议被称为停等协议。
- 处理ACK和NAK受损的几种方法
- 当接收到受损的时候,发送一个请求复述的报文。缺点是,复述内容和后面的内容会发生冲突,不知道谁是谁。
- 增加足够的检验和比特,使发送方不仅可以检测差错,还可以恢复差错。
- 当发送方收到含糊不清的ACK或NAK分组时,只需要重传当前数据即可。缺点是,接收方不知道接收到的分组是新的还是一次重传。
- 解决以上问题的方法,在数据分组中添加一新字段,让发送方对其数据分组编号,即将发送数据分组的序号放在该字段
- rdt2.1
- 使用了从接收方到发送方的肯定确认和否定确认。当接收到失序的分组时,接收方对所接收的分组发送一个肯定确认。如果收到受损的分组,接收方发送一个否认确认。
- rdt2.2
- rdt2.2实现了一个无NAK的可靠数据传输协议。如果不发送NAK,而是对上次正确接收的分组发送一个ACK,我们也能实现与NAK一样的效果。接收到同一分组的两个ACK,就知道该分组后的一个分组丢了。
- rdt2.1和rdt2.2最细微的差别是,接收方此时必须包含一个ACK报文所确认的分组序号。
经具有比特差错的丢包信道的可靠数据传输:rdt3.0
- 底层信道会发生丢包,协议需要关注两个问题,怎样检测丢包和发送丢包后该做些什么
- 实践中采用的方法是,发送方明智地选择一个时间值,以判定可能发生了丢包。如果在这个时间内没有收到ACK,则重传分组。
- 为了实现基于时间的重传机制,需要一个倒计时定时器,在一个给定的时间量过期后,可中断发送方。因此,发送方需要能做到:
- 每次发送一个分组(包括第一次分组和重传分组)时,便启动一个定时器
- 响应定时器中断(采取适当的动作)
- 终止定时器
- 因为分组序号在0和1之间交替,因此rdt3.0有时被称为比特交替协议(alternating-bit protocol)
- 数据传输协议的要点:检验和、序号、定时器、肯定和否定确认分组。
流水线可靠传输协议
- rdt3.0性能问题的核心在于它是一个停等协议。
- 解决这种特殊的性能问题的一个简单方法是:不使用停等方式运行,允许发送方发送多个分组而无需等待确认。
- 如图,发送方在等待确认之前发送3个报文,其利用率就提高了三倍
- 因为许多从发送方向接收方输送的分组可以被看成是填充到一条流水线中,故这种技术被称为流水线。
- 流水线技术会对可靠数据传输协议带来以下影响:
- 必须增加序号范围。因为每个输送中的分组必须有一个唯一的序号,而且也许有多个在输送中未确认的报文
- 协议的发送方和接收方两端也许必须缓存多个分组。发送方最低限度应当能缓冲那些已经发送但没有确认的分组
- 所需序号范围和对缓冲的要求取决于数据传输协议如何处理丢失、损坏及延时过大的分组。解决流水线的差错恢复有两种基本方法:回退N步(Go-Back-N,GBN)和选择重传(Selective Repeat,SR)
回退N步
- 在回退N步协议中,允许发送方发送多个分组而不需要等待确认,但它也受限于在流水线中未确认的分组数不能超过某个最大允许数N。
- 其实就是一个滑动窗口,
base-1
之前的是已经确认好的,base
是最早未被确认的分组,base
-nextseqnum-1
是已经发送但是还没有被确认的,nextseqnum
是下一个被发送的,nextseqnum
-base+N-1
是可以被立即发送的,base+N
是还不能被发送的。当base
被确认之后,窗口就可以往后移一格。 - N被称为窗口长度,GBN协议也常常被称为滑动窗口协议
- GBK必须响应三种类型的事件:
- 上层的调用。当上层调用
rdt_send()
时,发送方首先检测发送窗口是否已经有N个发送但未被确认的分组。如果没有,那就发一个。如果已经满了,发送方可能隐式地指示上层该窗口已满。上层有可能待会再来,也有可能发送方用一个缓存或者同步机制。 - 收到一个ACK。对序号为n的分组的确认采取累计确认的方式,表明接收方已正确接收到序号为n的以前且包括n在内的所有分组。
- 超时事件。如果出现超时,发送方重传所有已发送但未确认过的分组。
- 上层的调用。当上层调用
- GBK的接收方:接收方只能按序地接收,不能失序。失序就直接丢弃。因为它是滑窗机制,就算回一个ACK也没用。
选择重传
- GBK存在一些性能问题。尤其是当窗口长度和带宽时延积都很大时。单个分组的差错就能够引起GBK重传大量分组。
- 选择重传(SR)协议通过让发送方仅重传那些它怀疑在接收方出错(即丢失或受损)的分组而避免了不必要的重传。
- 发送方事件与动作
- 从上层收到数据。当上层接收到数据后,SR发送方检查下一个可用于该分组的序号。如果序号在发送方的窗口内,则将数据打包并发送;否则就像在GBN一样,要么数据缓存,要买么将其返回上层,待会再发。
- 超时。每个分组拥有自己的逻辑定时器,因此超时重发自己的分组就好了。
- 收到ACK。如果收到ACK,分组在窗口中,那就标记一下。如果等于
send_base
,则窗口序号向前移动到具有最小序号的未确认分组处。如果窗口移动了并且有序号落在窗口内的未发送分组,则发送这些分组。
- 接收方将确认一个正确接收的分组,而不管其是否按序。失序的分组将缓存直至所有丢失分组皆被收到为止,这时才将一批分组按序交付给上层。
- 如果序号在
rcv_base
-rcv_base+N-1
之间,那就回一个ACK,如果之前没收过,那就缓存起来 。该移动的,该给上层的,一样。 - 如果序号为
rcv_base-N
-rcv_base-1
内的分组被正确收到,那就一定要回一个ACK。 - 其他,那就忽略吧。
- 如果序号在
- 接收方重新确认(而不是忽略)已经收到过的那些序号小于当前窗口基序号的分组。
可靠数据传输机制及其用途的总结
机制 | 用途和说明 |
---|---|
检验和 | 用于检测在一个传输分组中的比特错误 |
定时器 | 用于超时/重传一个分组,可能该分组(或ACK)在信道中丢失了 |
序号 | 用于从发送方流向接收方的数据分组按顺序编号 |
确认 | 接收方用于告诉发送方一个分组或一组分组已被正确地接收到了 |
否定确认 | 接收方用于告诉发送方某个分组未被正确地接收 |
窗口、流水线 | 发送方也许被限制仅发送那些序号落在一个指定范围内的分组 |
面向连接的传输:TCP
- 为了可靠数据传输,TCP依赖许多基本原理,包括差错检测、重传、累计确认、定时器以及用于序号和确认号的首部字段
TCP连接
- TCP被称为是面向连接的,这是因为在一个应用进程可以开始向另一个应用进程发送数据之前,这两个进程必须先互相“握手”。即它们必须互相发送某些预备报文段,以建立确保数据传输的参数。
- TCP连接提供给的是全双工服务:如果一台主机上的进程A与另一台主机上的进程B存在一条TCP连接,那么应用层数据就可从进程B流向进程A的同时,也从进程A流向进程B。
- TCP连接总是点对点的,即在单个发送方与单个接收方之间的连接。
- TCP连接:客户首先发送一个特殊的TCP报文段,服务器用另一个特殊的TCP报文段来响应,最后客户再用第三个特殊报文段作为响应。这种连接建立过程叫做三次握手
- 前两个报文段不承载“有效负荷”,也就是不包含应用层数据;而第三个报文段可以承载有效载荷。
- 客户进程通过套接字传递数据流。TCP将这些数据引导到该连接的发送缓存。发送缓存是在三次握手初期设置的缓存之一。
- TCP不时在发送缓存中取出一块数据发送到另一端。TCP可从缓存中取出并放入报文段中的数据数量受限于最大报文段长度(MSS)。MSS通常根据最初确定的由本地发送主机发送的最大链路层帧长度。(即最大传输单元MTU)
- 当TCP在另一端接收到一个报文段后,该报文段的数据就被放入该TCP连接的接收缓存中
TCP报文段结构
![](https://i-blog.csdnimg.cn/blog_migrate/c802ef8240f52ad6813a8cb3e2db055d.png)
- TCP报文段由首部字段和一个数据字段组成。数据字段包含一块应用数据。
- MSS限制了报文段数据字段的最大长度。当TCP发送一个大文件,TCP通常将文件划分成长度为MSS的若干块。
- 首部包含内容:
- 源端口号和目的端口号,它被用于多路复用/分解来自或送到上层应用的数据。
- 检验和字段。
- 32比特的序号字段和32字段的确认号字段。这些字段被TCP发送方和接收方用来实现可靠数据传输服务。
- 16比特的接收窗口字段,该字段用于流量控制。
- 4比特的首部长度字段。该字段指示了32比特的字为单位的TCP首部长度。
- 可选与变长的选项字段。该字段用于发送方与接收方协商最大报文段长度(MSS)时,或在高速网络环境下窗口调节因子时使用。
- 6比特的标志字段。
ASK比特用于指示确认字段中的值是有效的,即该报文包括一个对已被成功接收报文段的确认。
RST、SYN、FIN比特用于连接建立和拆除。
PSH比特被设置的时候,就指示接收方应立即将数据交给上层。
URG比特用来指示报文段里存在着被发送端的上层实体置为“紧急”的数据。
紧急数据指针字段指出紧急数据的最后一个字节。
序号和确认号
- 这两个字段是TCP可靠传输服务的关键部分。
- TCP把数据看成一个无结构的、有序的字节流。
- 传输过程中,将被传输的字节流分割成n个MSS大小的字节流,并包装成报文段给网络层。
- 一个报文段的序号,就是该报文段首字节在字节流中的序号。
MSS为1000字节 第一个报文段分配序号为0 第二个为1000 以此类推
- 确认号:假设主机B给主机A发数据。主机A已经收到了0~535的所有字节,并且它本身打算给主机B发送一个报文段,那么主机A就会在报文段的确认号中填入536,表示它在期待收到536为序号的报文段。
- 另一个例子,如果主机A收到了0-535和900-100的报文段,但536为序号的报文段丢失了,主机A还是会将536作为确认号。因为TCP只确认该流中至第一个丢失字节为止的字节,所以TCP被称为提供累积确认。
- 那么,如何处理900-1000的报文段?方法有二,直接丢弃,或先保存着,等待缺少的字节填补空缺。实践中采用后者。
- 一条TCP连接的双方均可随机地选择初始序号。这样做可以减少将那些仍在网络中存在的来自两台主机之间先前已终止的连接的报文段,误认为是后来这两台主机之间新建连接所产生的有效报文段的可能性。
往返时间的估计与超时
可靠数据传输
- TCP在IP不可靠的尽力而为服务之上创建了一种可靠数据传输服务
- TCP的可靠数据传输服务确保一个进程从其接收缓存中读出的数据流是无损坏、无间隔、非冗余和按序的数据流;即该字节流与连接的另一端系统发送出的字节流是完全相同的。
- TCP发送方有3个与发送和重传有关的主要事件:从上层应用程序接收数据、定时器超时、收到ACK。
- 从上层应用程序接收程序:TCP从应用程序接收数据,将数据封装在一个报文段中,并将报文段交给IP。当报文段被传给IP时,就开启定时器。
- 定时器超时:TCP重传,然后重新计时。
- 接收来自接收方的确认报文段(ACK):TCP将ACK的值y与它的变量SendBase比较。(SendBase就是最早没有被确认的字节的序号)如果y>SendBase,则该ACK是在确认一个或多个先前未被确认的报文段。因此发送方更新它的SendBase变量。如果当前还有未被确认的报文段,TCP还要被重新启动定时器。(累计确认解决了很多问题,如下图)
- 假设,主机A与在第二种情况中完全一样,发送两个报文段。第一个报文段的确认报文在网络中丢失,但在超时事件发生之前主机A收到一个确认号为120的确认报文。主机A因而知道主机B已经收到序号为119及之前的所有字节,所以主机A不会重传。(累计确认的功劳)
超时间隔加倍
- 对于超时,TCP会很优雅地将超时时间间隔加倍。之前的超时,有可能是因为网络拥塞导致的,加倍超时间隔,防止源持续重传分组,使得网络拥塞更严重了。(有一种自适应的感觉)
快速重传
- TCP不用NAK,通过冗余ACK来判断是否有数据丢失。(还是累积确认的功劳)
- 如果TCP发送方接收到对相同数据的3个冗余ACK,把它作为一种指示,说明跟在这个已被确认3次的报文段之后的报文段已经丢失。一旦收到3个冗余ACK,TCP就执行快速重传(fast retransmit)
回退N步还是选择重传
- TCP发送方仅需维持已发送过但未被确认的字节的最小序号(SendBase)和下一个要发送的字节的需要(NextSeqNum)。
- TCP会将正确接收但失序的报文段缓存起来。
- N为窗口大小,当n<N的确认报文丢失,但其余的N-1个确认报文在分别超时以前到达发送端,TCP将重传至多一个报文段,即报文段n。此外,如果对报文段n+1的确认报文在确认报文n超时前到达,TCP甚至不会重传报文段n
- 对TCP提出的一种修改意见是所谓的选择确认,它允许TCP接收方有选择地确认失序报文段,而不是累积地确认最后一个正确接收的有序报文段。
流量控制
- 一条TCP连接每一侧主机都为该连接设置了接收缓存。当该TCP连接收到正确、按序的字节后,它就将数据放入接收缓存。
- 如果应用程序读取数据时相对缓慢,而发送方发送得太多、太快,发送的数据就很容易导致该连接的接收缓存溢出。
- TCP为它的应用程序提供了流量控制服务,以消除发送方使接收方缓存溢出的可能。
- 流量控制因此是一个速度匹配服务。
- TCP通过让发送方维护一个称为接收窗口的变量来提供流量控制。
- 接收窗口用于给发送方一个指示——该接收方还有多少可用的缓存空间。
- 接收缓存,用
RcvBuffer
表示其大小;LastByteRead
表示从缓存读出的数据流的最后一个字节的编号;LastByteRcvd
表示接受缓存中的数据流的最后一个字节的编号。 - 由于TCP不允许已分配的缓存溢出,下列必须成立:
LastByteRcvd - LastByteRead <= RcvBuffer
- 缓存可用空间:
rwnd = RcvBuffer - [LastByteRcvd - LastByteRead]
- 接收方通过把当前的rwnd值放入它发给发送方的报文段接收窗口字段中,通过发送方还有多少可用空间。
- 发送方需要跟踪两个两变量:
LastByteSent
,最后一个被发送字节的编号;LastByteAcked
最后一个被确认的字节的编号。 - 两者之差
LastByteAcked - LastByteSent
就是被发送但是还没有被确认的字节的个数。 - 因此,在发送方的整个生命周期,都需要保证:
LastByteAcked - LastByteSent <= rwnd
- 当rwnd为0的时候,接收方告诉发送方,然后发送方就不发送消息了。但是,接收方仅当它有数据或有确认要发的时候,才会发送报文段给发送方。那么,发送方就一直在等待,接收方又不主动发,就会造成拥塞。
- 因此,为了解决此问题,在发送方得知接收方的接受窗口大小为0的时候,还会继续发一个字节数据的报文段,这些报文段将会被接收方确认。最终缓存将开始清空,并且确认报文里包含一个非0的
rwnd
值。(类似于发送方一直轮询可不可以发送?)
TCP连接管理
- 假设一台主机(客户)上的一个进程想与另一台主机(服务器)上的进程建立一条连接。
- 客户应用进程首先通知客户TCP,它想建立一个与服务器上某个进程的连接。
- 客户中的TCP就会以以下方式与服务器的TCP建立一条连接(三次握手,重点掌握):
- 客户端的TCP首先向服务端的TCP发送一个特殊的TCP报文段。报文段不包含任何应用层信息。但在报文段首部的SYN标志位会被置为1。这个特殊的报文段被称为SYN报文段。客户端随机选择一个起始序号(
client_isn
),作为序号字段的内容。(此操作是为了避免某些安全性攻击) - SYN报文段到达服务器之后,为该TCP连接分配缓存和变量,并向该客户端TCP发送允许连接的报文段。该报文段也不包含任何应用层数据。首部字段包含:SYN被置1;确认号字段为
client_isn+1
;服务器选择自己的初始序号(server_isn
),并放置在序号字段。该报文被称为SYNACK报文段。 - 收到SYNACK报文段之后,客户端也分配缓存和变量。客户端发送一个报文,表示对允许连接的报文段进行确认。SYN被置为0;确认字段为server_isn+1。该报文可以携带客户端到服务器的数据。
- 客户端的TCP首先向服务端的TCP发送一个特殊的TCP报文段。报文段不包含任何应用层信息。但在报文段首部的SYN标志位会被置为1。这个特殊的报文段被称为SYN报文段。客户端随机选择一个起始序号(
- 为什么要三次握手,不是两次?个人理解:因为在前两次握手中,客户端和服务端各自交换了起始序号,服务器给客户端发送的序号字段,如果没有第三次握手,就没办法确认客户端有没有收到。而且,第三次握手携带了应用层数据,所以其实对效率并没有什么影响,无伤大雅还更加安全,何乐而不为呢。
- 客户端TCP关闭与服务器TCP的连接(四次挥手,重点掌握)
- 客户端首部字段的FIN标志位,置1,发送给服务器。
- 服务器收到报文段之后,回一个确认报文段。
- 服务器发送自己的终止报文段,FIN置1。
- 客户端对终止报文表示确认。最后两者资源均释放。
- TCP客户端状态转换
- SYN洪泛攻击:攻击者发送大量的TCP SYN报文段而不完成第三次握手的操作。(也就是频繁发送第一次握手)服务器不断为这些半开连接分配资源,导致服务器的连接资源被消耗殆尽。
- TCP服务端状态转换
拥塞控制原理
拥塞原因及代价
- 随着主机增加其发送速率并使网络变得拥塞。