第6章 传输层(详解TCP的三次握手与四次挥手)

第6章 传输层

传输层简介

传输层为网络应用程序提供了一个接口,而且可以对网络传输提供了可选的错误检测、流量控制和验证功能。TCP/IP传输层包含不少有用的协议,可以提供数据在网络传输所需的必要寻址信息。但寻址和路由只是传输层的部分功能。tcp/ip的开发者知道你他们须要在网际层上添加另一层,并经过这一层提供的额外必要特性来使用IP。传输层协议须要提供如下功能:html

  • 为网络应用程序提供接口:也就是为应用程序提供访问网络的途径。设计者但愿不只仅可以向目的计算机传递数据,还可以向目的计算机上的特定程序传递数据。
  • 多路复用/多路分解机制:这里的多路复用表示从不一样应用程序和计算机接收数据,再把数据传递到目的计算机上的接收程序。换句话说,传输层必须可以同时支持多个网络程序和管理传递给网际层的数据流。在接收端,传输层必须可以从网际层接收数据,把他转发到多个程序,这种功能被称为多路分解,它可让一台计算机同时支持多个网络程序,好比一个WEB浏览器、一个E-mail客户端和一个文件共享应用程序。多路复用/多路分解的另外一个做用是可让一个应用程序同时保持与多台计算机的链接。
  • 错误检测、流量控制和验证:协议系统须要一种全面的机制来确保发送端与接收端之间的数据传输。

最后一项是变化最多的。质量保证一般会在收益与代价之间寻找平衡。精心的质量保证系统会提升传输的可靠性,但须要以增长网络流量和处理时间为代价。对于大多数应用程序来讲,这种额外的保证并不值得。所以传输层提供了两种到达网络的方式,他们都具备支持应用程序所必须的接口和多路复用/多路分解功能,但在质量保证方面所采用的方法有很大不一样,以下所示:git

  • 传输控制协议(TCP):TCP提供了完善的错误控制和流量控制,可以确保数据正确传输,它是一个面向链接的协议。
  • 用户数据报协议(UDP):UDP只提供了很是基本的错误检测,用于不须要TCP精细控制功能的场合,它是一个无链接的协议。

面向链接的协议和无链接的协议

为了针对不一样状况提供不一样程序的质量保证,传输层提供了两种不一样的协议原型github

  • 面向链接的协议:会在通讯计算机之间创建并维护一个链接,而且在通讯过程当中监视链接的状态。换句话说,经过网络传输的每一个数据包都会有一个确认,发送端计算机会记录状态信息来确保每一个数据包都被正确无误地接收了,而且在须要时会重发数据。当数据传输结束以后,发送端和接收端计算机会以适当方式关闭链接。
  • 无链接的协议:以单向方式向目的发送数据报,不承担通知目的计算机关于数据发送的职责。目的计算机接收到数据后也不须要向源计算机返回状态信息。

端口和套接字

在TCP/IP系统中,应用程序能够使用端口号经过TCP或UDP指定数据目的地端口是一个预约义的内部地址,充当从应用程序到传输层或是从传输层到应用程序之间的通路。shell

进一步观察传输层这种与应用程序相关的寻址体制,就会发现TCP和UDP数据实际是被发送到一个套接字上的。套接字是一个由IP地址和端口号组成的地址。例如,套接字地址111.121.131.141.21指向IP地址为111.121.131.141的计算机的端口21。api

下面的例子里展现了一台计算机如何经过套接字访问目的计算机上的一个应用程序。浏览器

服务 TCP端口号 简要描述
tcpmux 1 TCP端口服务多路复用器
compressnet 2 管理工具
ftp 21 文件传输协议控制
ssh 22 安全shell
smtp 25 简单邮件传输协议
http 80 WWW服务
服务 UDP端口号 简要描述
echo 7 回显
discard 9 抛弃或空
domain 53 域名服务程序(DNS)
systat 11 用户
daytime 13 时间
qotd 17 每日引用
  1. 计算机A经过一个熟知的端口向计算机B上的应用程序发起一个链接。熟知端口是由互联网数字分配机构(IANA)分配给特定程序的端口。上表列出了一些熟知的TCP和UDP端口。熟知的端口与IP地址组合以后就构成了计算机A的目的套接字。链接请求包含着一个数据字段,告诉计算机B使用什么套接字向计算机A返回信息,这也就是计算机A的源套接字地址
  2. 计算机B经过熟知端口接收到来自计算机A的请求,向做为计算机A源地址的套接字发送一个响应。这个套接字就成为计算机B上的应用程序向计算机A上的应用程序发送消息的目的地址

多路复用/多路分解

套接字寻址系统使得TCP和UDP可以执行传输层另外一个重要任务:多路复用和多路分解。多路复用是指多个来源的数据导向一个输出,而多路分解是把一个来源接收的数据发送到多个输出。缓存

多路传输/多路分解分解让TCP/IP协议栈较低层的协议没必要关心哪一个程序在传输数据。与应用程序相关的操做都由传输层完成了,数据经过一个与应用程序无关的管道在传输层与网际层之间传递。安全

多路复用和多路分解的关键在于套接字地址。套接字的地址包含了IP地址与端口号,为特定计算机上的特定应用程序提供了一个惟一的标识。全部客户端计算机使用熟知的TCP端口21链接到FTP服务器,但针对每台我的计算机的目的套接字是不一样的。相似地,运行于这台FTP服务器上所有网络应用程序都使用服务器的IP地址,但只有FTP服务程序使用由IP地址和TCP端口号21组成的套接字地址服务器

理解TCP和UDP

本章前面提到,TCP是个面向链接的协议,提供了全面的错误控制和流量控制。UDP是个无链接协议,错误控制也简单得多。能够这样说,TCP是为了可靠性,而UDP是为了速度。必需要支持交互会话的应用程序,好比Talnet和FTP,就会使用TCP。而本身实现错误检测或不须要过多错误控制的应用程序会倾向于使用UDP。网络

软件开发人员在设计网络应用程序时能够选择使用TCP或UDP做为传输协议。UDP的控制机制虽然比较简单,但这并非它的缺点。首先,较简单的质量控制并不必定意味着低质量。对于大多数应用程序来讲,TCP提供的错误检测与控制是彻底没有必要的。在一些须要控制错误和流量控制的状况下,有些开发人员更愿意在应用程序自己内提供这些控制功能,从而能够根据实际须要进行控制,并使用较简单的UDP进行网络访问。例如,应用层的远程过程调用RPC协议可以支持复杂的应用程序,但RPC开发人员有时倾向于在传输层使用UDP,而且利用应用程序提供错误控制和流量控制,而不是使用速度较慢的TCP链接

TCP:面向链接的传输协议

它包括如下重要特性:

  • 面向流的处理:TCP以流的方式处理数据。换句话说,TCP能够一个字节一个字节地接收数据,而不是一次接收一个预约义格式的数据块。TCP把接收到的数据组成长度不定的段,再传递到网际层。
  • 从新排序:若是数据以错误的顺序到达目的,TCP模块可以对数据从新排序来恢复原始顺序。
  • 流量控制:TCP的流量控制特性可以确保数据传输不会超过目的计算机接受数据的能力。因为现实世界里会有各类不一样的应用环境,处理器速度和缓存区大小的差异也可能很大,因此这种流控制能力是很是重要的。
  • 优先级与安全:国防部对TCP的规范要求能够为TCP链接设置可选的安全级别和优先级,但不少TCP实现并无提供这些安全和优先级特性。
  • 适当的关闭:TCP像重视创建链接同样重视关闭链接的工做,以确保在链接关闭以前,全部数据段都被发送和接收了。

1.TCP数据格式

  • 源端口(16位):分配给源计算机上的应用程序的端口号
  • 目的端口(16位):分配给目的计算机上的应用程序的端口号
  • 序列号(32位):当SYN标记不为1时,这是当前数据分段第一个字节的序列号;若是SYN的值是1,这个字段的值就是初始序列值(ISN),用于对序列号进行同步,这时第一个字节的序列号比这个字段的值大1(也就是ISN加1)
  • 确认号(32位):用于确认已经接收到的数据分段,其值是接收计算机即将接收的下一个序列号,也就是下一个接收到的字节的序列号加1。
  • 数据偏移(4位):这个字段表示报头的长度,也就是告诉接收端的TCP软件数据从何开始。这个值的单位是32位的字
  • 保留(6位):保留字段,为TCP未来的发展预留空间,目前必须所有是0。
  • 控制标记(分别占用1位):控制标记用于表示数据分段的特殊信息
    • URG: 为1时表示当前数据分段是紧急的,也会让“紧急指针”字段的值有意义。
    • ACK: 为1时表示“确认号”字段是有意义的。
    • PSH: 为1时让TCP软件把目前收到的所有数据都经过管道传递给接收应用程序
    • RST: 为1时会重置链接
    • SYN:为1时表示序列号将被同步,说明这是一个链接的开始。请参见稍后介绍的三次握手
    • FIN:为1时表示发送端计算机已经没有数据须要发送了。这个标记用于关闭一个链接
  • 窗口(16位):用于流量控制的参数。它定义了发送端计算机的发送序列号能够超过最后一个已肯定序列号的数量。也就是说,发送方没必要等待每一个数据段被确认接收以后才发送下一个数据分段,容许已经确认接收的序列号与正在发送的序列号有必定的差异,但必须在适当范围之中
  • 校验和(16位):用于检验数据分段的完整性。接收端计算机会根据接收到的数据分段计算校验和,而且把结构与这个字段的值进行比较。TCP和UDP在计算校验和时包含一个具备IP地址的伪报头。
  • 紧急指针(16位):这是一个偏移量指针,指向标记紧急信息开始的序列号
  • 选项:指定一些可选设置中的某一项
  • 填充:额外填充的0,以确保数据从32位字的边界开始
  • 数据:数据分段中的数据

2.TCP链接

TCP的功能之一是为应用程序提供访问网络的接口。这个接口是经过TCP端口提供的,而为了经过端口提供链接,必须打开TCP与应用程序的接口。TCP支持如下两种打开状态。

  • 被动打开:某个应用程序进程通知TCP准备经过TCP端口接收链接,这样就会打开TCP到应用程序的链接,从而为参与链接请求作准备
  • 主动打开:程序要求TCP发起与另外一台计算机(处于被动打开状态)的链接,这就是主动打开状态,实际上TCP能够对一个处于主动打开状态的计算机初发起链接,已解决两台计算机可能同时尝试创建链接的问题。

在一般状况下,想接收链接的应用程序(好比FTP服务器)会把自身及其TCP端口置于被动打开状态。在客户端计算机上,FTP客户端的TCP状态通常是关闭的,直到用户发起一个从FTP客户端到FTP服务器的链接,这对于客户端来讲就是主动打开的。处于主动打开状态的计算机上的TCP软件会开始一些用于创建链接的信息交换,这种信息交换被称为“三次握手”,稍后详细介绍

TCP发送的数据分段的长度是不定的。在一个数据分段内,每字节数据都被分配一个序列号。接收端计算机必须为接收到的每一个字节数据都发送一确认信号。所以TCP通讯是一种传输与确认的系统。TCP报头中的“序列号”和“确认号”字段让通讯的TCP软件可以按期更新传输的状态。

实际上,数据分段中并非为每一个字节都单独编了一个序列号。而是在报头的“序列号”字段指定了数据分段第一个字节的序列号。

若是数据分段被成功接收,接受端计算机会利用“确认号”字段告诉发送端计算机它接收到哪一个字节。在确认消息中,“确认号”字段的值是已接收的最后一个序列号加1.换句话说,“确认号”字段中的值是计算机准备接收的下一个序列号。

3.创建链接

为了让序列/确认系统正常工做,计算机必须对序列号进行同步。换句话说,计算机B必须知道计算机A的初始化序列号(ISN)。计算机A也必须知道计算机B使用什么ISN开始传输数据。

这个序列号的同步过程被称为三次握手。三次握手老是发生在TCP链接创建的初期,其步骤以下:

  1. 计算机A发送一个数据分段,其中的参数是:
    SYN = 1
    ACK = 0
    序列号 = X (X是计算机A的ISN)
    处于主动打开状态的计算机(计算机A)发送一个数据分段,其中SYN为1,ACK为0.SYN是同步(syncchronize)的缩写,它表示在尝试创建一个链接。第一个数据分段的报头还包含初始序列号(ISN),标记了计算机将传输的第一个字节的序列号。也就是说,要发送给计算机B的第1个字节的序列号是ISN加1
  2. 计算机B接受到计算机A的数据分段,返回一个数据分段,其中的参数是:
    SYN = 1
    ACK = 1 (确认号字段将包含一个值)
    序列号 = Y (Y是计算机B的ISN)
    确认号 = M + 1 (其中M是从计算机A接收到的最后一个序列号)
  3. 计算机A向计算机B发送一个数据分段,确认收到计算机B的ISN:
    SYN = 0
    ACK = 1
    序列号 = 序列中下一个号码 (M+1)
    确认号 = N + 1 (其中N是从计算机B接收到的最后一个序列号)

在这三次握手完成以后,链接就被打开了,TCP模块就利用序列和确信机制发送和接收数据。

为何须要“三次握手”

在谢希仁的《计算机网络》中是这样说的,为了防止已失效的链接报文段又发送到了服务器端,从而产生错误
在书中同时举了一个例子:“已失效的链接报文段”产生在这样一种状况下:client发出的第一个链接请求报文段并无消失,而是在某个网络结点长时间的滞留了,以至于延误到释放之后的时间才到达server。原本这是一个早已失效的报文段。但server收到此失效的链接请求报文段以后,就误觉得是client再次发过来的一个新的链接请求。假设没有“三次握手”,那么只要server发出确认,新的链接就创建了。因为如今client并无发出创建链接的请求,所以不会理睬server的确认,也不会向server发送数据。但server却觉得新的运输链接已经创建了,并一直等待client发来数据。这样,server的资源就白白浪费了。

4.TCP流量控制

TCP报头中的“窗口”字段为链接提供了一种流量控制机制,其目的是防止发送端计算机不要发送得太快,以免接收端计算机来不及处理接收到的数据而致使数据丢失。TCP使用的流量控制方法被称为“滑动窗口”方法。接收端计算机利用“窗口”字段来定义一个超过最后一个已确认序列号的序列号“窗口”。在这个范围内的序列号才容许发送端计算机进行发送。发送端计算机在没有接收到下一个确认消息以前不能发送超过这个窗口的序列号。

5.关闭链接

当须要关闭链接时,计算机开始关闭过程,计算机A发送一个数据分段,其中的FIN标记设置为1。以后应用程序进入“结束--等待”状态。在这个状态中,计算机A的TCP软件继续接收数据分段,并处理已经在序列中的数据分段,但再也不从应用程序接收数据了。当计算机B接收到FIN数据分段时,它返回对FIN的确认信息,而后发送剩余的数据分段,通知本地应用程序接收到了FIN消息。计算机B向计算机A发送一个FIN数据分段,计算机A会返回确认消息,链接就被关闭了。

四次挥手的表述

  1. 计算机A发送一个FIN标志,此时计算机A进入FIN_WAIT状态
  2. 计算机B收到了FIN报文段,向计算机A返回一个ACK字段,告诉A我赞成你的关闭请求
  3. 计算机B继续处理剩余数据,处理完向A发送FIN报文段,请求关闭链接,同时B进入LAST_ACK状态
  4. 计算机A接收到B发送的FIN报文段,向B发送ACK报文段,而后主机1进入TIME_WAIT状态;主机B收到后,就关闭链接了。A等待2MSL后依然没有收到回复,A也能够关闭链接了。

UDP: 无链接传输协议

虽然UDP有时被认为没有错误检验功能,但实际上它可以执行基本的错误检验,所以,能够说UDP具备有限的错误检验功能。UDP数据报中包含一个检验和,接收端计算机能够利用它来检验数据的完整性(通常状况下,这个校验和检查是可选的,并且可以被接收端计算机禁用以加快对接收数据的处理)。UDP数据报中有个一个伪报头,包含了数据报的目的地址,从而提供了发现数据报错误传输的手段。另外,若是UDP接收模块接收到一个发给未激活或未定义UDP端口的数据报,它会返回一个ICMP消息,通知源计算机这个端口是不可到达的。

其次,UDP没有像TCP那样提供数据的从新排序功能。在大型网络上,数据分段可能会通过不一样的路径,因为路由器缓存而产生明显延时,这时从新排序功能是很是有意义的。而在局域网上,虽然UDP没有从新排序功能,但通常不会致使不可靠的接收。

UDP协议的主要用途是把数据报传递给应用层。UDP协议的功能简单,其报头结构也很简单。UDP不会从新传输丢失或损坏的数据报、从新排列混乱的接收数据、消除重复的数据报、确认数据报的接收、创建或是终止链接。它主要是在程序没必要使用TCP链接开销的状况下发送和接收数据报的一种方式。若是上述功能对于应用程序来讲是必需的,它能够本身提供这些功能。

UDP头包含4个16位字段

  • 源端口: 这个字段占据UDP报头的前16位,一般包含发送数据报的应用程序所使用的UDP端口。接收端的应用程序利用这个字段的值做为发送响应的目的地址。这个字段是可选的。发送端的应用程序不是必定要把本身的端口写在这个字段上。若是发送端的应用程序不写入其端口号,就应该把这个字段全置0。显然,若是这个字段没有包含有效的端口地址,接收端的应用程序就不能发送响应。而后有时这可能正是咱们想要的功能,好比单向消息就不须要响应
  • 目的端口:这16位字段包含的端口地址是接收端计算机上UDP软件使用的端口
  • 长度:这16位字典以字节为单位表示UDP数据报的长度。这个长度包括了UDP报头和UDP数据载荷。由于UDP报头的长度是8字节,因此这个值最小是8。
  • 校验和:这个16位字段能够校验数据在传输过程当中是否损坏。校验和是对二进制数据串执行特殊计算而获得的结果。对于UDP来讲,校验和是基于伪报头、UDP报头、UDP数据和填充的0而计算的。源计算机生成校验和,目的计算机对它进行检验,让客户端用程序可以判断数据报是否完整。

因为实际的UDP报头并不包含源IP地址或目标IP地址,数据报可能会被传输到错误的计算机或服务。校验和使用部分数据来自于从IP报头(被称为伪报头)提取的值,这个伪报头包含了目的IP地址信息,让接收段计算机可以判断UDP数据报是否被错误支付。

防火墙和端口

防火墙是一个系统,保护局域网不被来自Internet的未受权用户攻击。“防火墙”的基本特性就是阻断对特定TCP和UDP端口的访问。实际上,“防火墙”一词有时具备动词特性,表示关闭对端口的访问。

例如,为了发起与服务器的安全Shell(SSH)会话,客户端计算机必须向SSH的熟知端(TCP22)发起一个请求。若是担忧外部入侵者会经过SSH访问咱们的服务器,一种方法是配置服务器来中止使用端口22。这样一来,服务器就关闭了SSH的应用,但也禁止了局域网中的合法用户使用SSH来完成正常操做。

另外一种方法是安装防火墙,而且配置防火墙来阻断对TCP端口22的访问,这样作的结果是,局域网中的用户可以在防火墙以内自由地访问服务器上的TCP端口22,而局域网以外的网络用户就不能访问服务器的TCP端口22,也就不能经过SSH访问服务器了。事实上,这时Internet上的用户不能经过SSH访问局域网中的任何计算机。

场景中使用SSH的TCP端口22做为示例。防火墙一般会阻断可能产生安全威胁的任何或所有端口。网络管理员通常会阻断对所有端口的访问,除了必须的端口,好比处理E-mail的端口。在链接Internet的计算机上,好比Web服务器,一般会在外部放置一个防火墙,从而避免对这台对这台计算机的访问致使对局域网的非法访问


2017/4/3 更新

昨晚在腾讯笔试题中又遇到了几道三次握手的题目,很遗憾没有作对,现再继续整理一下TCP通讯过程,如图所示:

TCP通讯过程包括三个步骤

TCP通讯过程详细版

三次握手各个状态的解释以下:

  1. CLOSED:起始点,在超时或者链接关闭时候进入此状态,这并非一个真正的状态,而是这个状态图假想起点。
  2. LISTEN:服务器端等待链接的状态,服务器通过socket,bind,listen函数以后进入此状态,开始监听客户端发过来的链接请求。此称为应用程序被动打开(等到客户端链接请求)
  3. SYN_SEND:第一次握手发生阶段,客户端发起链接。客户端调用connect,发送SYN给服务器端,而后进入SYN_SENT状态,等待服务器端确认。若是服务器端不能链接,则直接进入CLOSED状态。
  4. SYN_RCVD:第二次握手发生阶段,跟3对应,服务器端接收到了客户端的SYN,此时服务器从LISTEN状态进入SYN_RCVD状态,同时服务器回应一个ACK,而后再发送一个SYN即SYN+ACK给客户端。
  5. ESTABLISHED: 第三次握手阶段,客户端接收到服务器端的ACK包以后,也会发送一个ACK确认包,发送以后,客户端进入ESLABLISHED状态,代表客户端这边已经准备好了。TCP须要两边准备好了才能够进行数据运输。服务器端接收到客户端的ACK后会从SYN_RCVD状态转移到ESTABLISHED状态,就能够进行后面的数据运输了。因此,ESLABLISHED也能够说是一个数据传送状态。

四次挥手各类状态的解释以下:

  1. FIN_WAIT_1:第一次挥手。主动关闭的一方终止链接时,发送FIN给对方,此时进入到FIN_WAIT1状态,而后等待对方返回ACK。
  2. CLOSE_WAIT接收到FIN以后,被动关闭的一方进入此状态。具体动做是接收到FIN后,发送ACK。之因此叫CLOSE_WAIT能够理解为被动关闭的一方此时正在等待
  3. FIN_WAIT_2接收到被动方发出的ACK时,进入该状态
  4. LAST_ACK:被动方发起关闭请求,由状态2进入该状态,具体动做是发送FIN给主动关闭请求的一方
  5. CLOSEING:表示你发送FIN报文后,并无收到对方的ACK报文,反而收到了对方的FIN报文。这种状况主要出如今双方几乎同时close一个socket,那么就出现了双方同时发送FIN报文的状况
  6. TIME_WAIT:共有三个状态会进入该状态
    • CLOSEING进入:客户端发起关闭请求,发送FIN以后等待服务器回应ACK,但此时服务器端同时也发起关闭请求,也发送了FIN,且客户端先收到FIN,后接收到ACK
    • FIN_WAIT_1进入:发起关闭后,发送了FIN,等待ACK的时候,正好服务器端发起请求,发送了FIN,这时客户端接收到了先前的ACK,也收到了对方的FIN,而后发送ACK,与CLOSEING进入的状态不一样的是接收到FIN和ACK的前后顺序,先收到ACK,后收到FIN
    • FIN_WAIT_2进入:这是与上面两种状态不一样的状况,主动方在完成自身发起的主动关闭请求后,接收到了对方发送过来的FIN,而后回应ACK

相关问题

为何TIME_WAIT状态还须要等2MSL后才能返回到CLOSED状态?

答:这是由于:虽然对方赞成关闭链接了,并且握手的4个报文也都协调和发送完毕,按理说能够直接回到CLOSED状态;可是由于咱们必须假想网络是不可靠的,你没法保证最后发送的ACK报文会必定被对方收到,所以对方处于LAST_ACK状态下的socket可能会由于超时未收到ACK报文,而重发FIN报文,这个TIME_WAIT的做用就是用来重发可能丢失的ACK报文

为何要有TIME_WAIT状态?

答:

  1. 防止上一次链接中的包,迷路从新出现,影响新链接(通过2msl,上一次链接中全部的重复包都会消失)
  2. 可靠的关闭TCP链接。在主动关闭后发送最后一个ACK,有可能丢失,这时被动方会从新发FIN,若是这时主动方处于CLOSED状态,就会响应rst而不是ack。因此主动方要处于TIME_WAIT状态,而不能是CLOSED。

参考连接:
TCP三次握手和Time-Wait状态
什么是2MSL
TCP的三次握手以及TCP状态转换图详解
TCP状态转换图详解

相关文章
相关标签/搜索