61阅读

传输层协议-Internet 传输层协议

发布时间:2018-02-19 所属栏目:协议类型

一 : Internet 传输层协议

本章介绍了 Internet 传输层的两个重要协议 TCP 和 UDP ,包括这两种协议的报文格式和工作原理。特别地,本章详细介绍了 TCP 的连接建立与关闭,以及连接建立与关闭过程的状态转换。

3.1 引言

Internet 在传输层有两种主要的协议:一种是面向连接的协议 TCP ,一种是无连接的协议 UDP 。由于 UDP 基本上是在 IP 的基础上增加一个短的报头而得到的,比较简单,因此本章将先介绍 UDP ,然后再重点介绍 TCP 。

在TCP/IP 协议簇中, IP 提供在主机之间传送数据报的能力,每个数据报根据其目的主机的 IP 地址进行在 Internet 中的路由选择。传输层协议为应用层提供的是进程之间的通信服务。为了在给定的主机上能识别多个目的地址,同时允许多个应用程序在同一台主机上工作并能独立地进行数据报的发送和接收, TCP/UDP 提供了应用程序之间传送数据报的基本机制,它们提供的协议端口能够区分一台机器上运行的多个程序。

也就是说, TCP/UDP 使用 IP 地址标识网上主机,使用端口号来标识应用进程,即 TCP/UDP 用主机 IP 地址和为应用进程分配的端口号来标识应用进程。端口号是 16 位的无符号整数, TCP 的端口号和 UDP 的端口号是两个独立的序列。尽管相互独立,如果 TCP 和 UDP 同时提供某种知名服务,两个协议通常选择相同的端口号。这纯粹是为了使用方便,而不是协议本身的要求。利用端口号,一台主机上多个进程可以同时使用 TCP/UDP 提供的传输服务,并且这种通信是端到端的,它的数据由 IP 传递,但与 IP 数据报的传递路径无关。网络通信中用一个三元组可以在全局唯一标志一个应用进程:

(协议,本地地址,本地端口号)

这样一个三元组,叫做一个半相关( half-association ),它指定连接的每半部分。一个完整的网间进程通信需要由两个进程组成,并且只能使用同一种高层协议。也就是说,不可能通信的一端用 TCP 协议,而另一端用 UDP 协议。因此一个完整的网间通信需要一个五元组来标识:

(协议,本地地址,本地端口号,远地地址,远地端口号)

这样一个五元组,叫做一个相关( association ),即两个协议相同的半相关才能组合成一个合适的相关,或完全指定组成一连接。

端口号的分配是一个重要问题。有两种基本分配方式:第一种叫全局分配,这是一种集中控制方式,由一个公认的中央机构根据用户需要进行统一分配,并将结果公布于众。第二种是本地分配,又称动态连接,即进程需要访问传输层服务时,向本地操作系统提出申请,操作系统返回一个本地唯一的端口号,进程再通过合适的系统调用将自己与该端口号联系起来(绑扎)。 TCP/UDP 端口号的分配中综合了上述两种方式。 TCP/UDP 将端口号分为两部分,少量的作为保留端口,以全局方式分配给服务进程。因此,每一个标准服务器都拥有一个全局公认的端口(即周知口, well-known port ),即使在不同机器上,其端口号也相同。剩余的为自由端口,以本地方式进行分配。表 3-1 列出了常用的 TCP/UDP 周知端口号。

表 3-1 常用周知端口号列表

端口号

协议

关键词

UNIX 关键词

描述

1

TCP

TCPMUX



TCP 复用器

7

TCP/UDP

ECHO

echo

回送

9

TCP/UDP

DISCARD

discard

丢弃

15

TCP/UDP



netstat

网络状态程序

20

TCP

FTP-DATA

ftp-data

文件传输协议(数据)

21

TCP

FTP

ftp

文件传输协议

22

TCP/UDP

SSH

ssh

安全 Shell 远程登录协议

23

TCP

TELNET

telnet

远程登录

25

TCP

SMTP

smtp

简单邮件传输协议

37

TCP/UDP



time

时间

42

TCP/UDP

NAMESERVER

name

主机名字服务器

43

TCP/UDP

NICNAME

whois

是谁

53

TCP/UDP

DOMAIN

nameserver

域名服务器

67

UDP

BOOTPS

bootps

引导协议服务器

68

UDP

BOOTPC

bootpc

引导协议客户

69

UDP

TFTP

tftp

简单文件传送协议

79

TCP

FINGER

finger

Finger

80

TCP

HTTP

http

超文本传输协议

88

TCP

KERBEROS

kerberos

Kerberos 协议

93

TCP

DCP



设备控制协议

101

TCP

HOSTNAME

hostnames

NIC 主机名字服务器

110

TCP

POP3

pop3

邮局协议版本 3

111

TCP/UDP

SUNRPC

sunrpc

Sun Microsystems RPC

119

TCP

NNTP

nntp

USENET 新闻传送协议

123

UDP

NTP

ntp

网络时间协议

139

TCP

NETBIOS-SSN



NETBIOS 会话协议

161

UDP



snmp

简单网络管理协议

162

UDP



snmp-trap

SNMP 陷阱

389

TCP

LDAP

ldap

轻量目录访问协议

443

TCP

HTTPS

https

安全 HTTP 协议

513

UDP



who

UNIX rwho daemon

514

UDP



syslog

系统日志

525

UDP



timed

UNIX time daemon

546

TCP

DHCP-CLIENT

dhcp-client

动态主机配置协议客户

547

TCP

DHCP-SERVER

dhcp-server

动态主机配置协议服务器

TCP 是一种有连接的传输服务,它提供可靠的传输,是大部分 Internet 应用的基础。 UDP 提供的是一种无连接服务,每个数据包独立传输,在传统的应用中因为不能像 TCP 那样保证数据的可靠传输而应用较少。但是对于新的实时视频、音频数据的传输来说,因为不能容忍 TCP 重传带来的时延,常常建立在 UDP 之上。 UDP 为互联网上实时视频、音频服务提供了极好的实验环境。

3.2 用户数据报协议 UDP

UDP(User Datagram Protocol) 是一个简单的面向数据报的传输层协议,进程的每个输出操作都正好产生一个 UDP 数据报,并组装成一份待发送的 IP 数据报。 UDP 不提供可靠性,它把应用程序传给 IP 层的数据发送出去,但是并不保证它们能到达目的地。应用程序必须关心 IP 数据报的长度。如果它超过网络的 MTU ,那么就要对 IP 数据报进行分片。 RFC 768 [Postel 1980] 是 UDP 的正式规范。

3.2.1 UDP 报文格式

每个 UDP 报文成为一个用户数据报,分 UDP 报头和 UDP 数据区两部分。报头由四个 16 位长的字段组成,分别说明该报文的源端口、目的端口、报文长度以及校验和。 UDP 报文格式如图 3-1 所示。

0

16 31

UDP 源端口

UDP 目的端口

UDP 报文长度

UDP 校验和

数据



图 3-1 UDP 报文格式

UDP 源端口字段和目的端口字段包含了 16 位的 UDP 协议端口号,表示发送进程和接收进程。 UDP 长度字段指的是 UDP 报头和 UDP 数据的字节长度,该字段的最小值为 8 字节(发送一份 0 字节的 UDP 数据报是可以的)。 UDP 检验和覆盖 UDP 报头和 UDP 数据。 UDP 和 TCP 在报头中都有覆盖它们报头和数据的检验和。 UDP 的检验和是可选的,如果该字段值为 0 表明不进行校验。一般来说,使用校验和字段是必要的。

3.2.2 UDP 的封装与协议的分层

在第 1 章介绍的 TCP/IP 协议层次结构模型中(参见图 1-3 ), UDP 位于 IP 层之上。应用程序访问 UDP 层,然后使用 IP 层传送数据报,如图 3-2 所示。

将 UDP 层放在 IP 层之上,表示一个 UDP 报文在 Internet 中传输时要封装到 IP 数据报中。最后,网络接口层将数据包封装到一个帧中再进行物理传输通道上的传输。封装过程如图 3-3 所示。

概念性层次

UDP 报头

UDP 数据区

应用

用户数据报( UDP )

IP 报头

IP 数据区

互联网( IP )

网络接口

帧头

帧数据区

图 3-2 分层模型中的 UDP 层

图 3-3 UDP 的封装

由图可知, IP 层的报头指明了源主机和目的主机的地址,而 UDP 层的报头指明了主机上的源端口和目的端口。 IP 层和 UDP 层之间的职责是清楚而明确的: IP 层指负责在 Internet 上的一对主机之间进行数据传输,而 UDP 层只负责对一台主机上的复用的多个源端口或目的端口进行区分。

3.2.3 UDP 的复用、分解与端口

UDP 也提供复用和分解的功能。它接收多个应用程序送来的数据报,把它们送给 IP 层区传输,同时它接受 IP 层送来的 UDP 数据报,把它们送给对应的应用程序。

从概念上讲,所有的 UDP 软件与应用程序之间的复用和分解都要通过端口机制来实现。实际上每个应用程序在发送数据报之前必须与操作系统进行协商以获得协议端口和相应的端口号。凡是利用指定的端口发送数据报的应用程序都要把端口号放入 UDP 报文中的源端口字段中。

UDP 的分解操作如图 3-4 所示, UDP 从 IP 层接收了数据报之后,根据 UDP 的目的端口号进行分解操作。

3.3 传输控制协议 TCP

TCP(Transfer Control Protocol) 是专门设计用于在不可靠的 Internet 上提供可靠的、端到端的字节流通信的协议。 Internet 不同于一个单独的网络,不同部分可能具有不同的拓扑结构、带宽、延迟、分组大小以及其它特性。 TCP 被设计成能动态满足 Internet 的要求,并且足以健壮地面对多种出错。 RFC 793 [Postel 1981] 是 TCP 的正式规范。

3.3.1 可靠的数据流传输

UDP 提供的服务是不可靠的数据传送服务,当传送过程中出现差错、网络软件发生故障或网络负载太重时,分组可能会丢失,数据可能被破坏。这就需要应用程序负责进行差错检测和恢复工作,对传输数据量很大的应用来说,采用这种不可靠的数据传输是不合适的。因此需要有一种可靠的数据流传输方法,这就是 TCP 。 TCP 提供的可靠传输服务有如下五个特征:面向数据流:当两个应用程序传输大量数据时,将这些数据当作一个可划分为字

节的比特流。在传输时,在接收方收到的字节流与发送方发出的完全一样。 虚电路连接:在传输开始之前,接收应用程序和发送应用程序都要与操作系统进行交互,双方操作系统的协议软件模块通过在互联网络上传送报文来进行通信,进行数据传输的准备与建立连接。通常用“虚电路”这个术语来描述这种连接,因为对应用程序来说这种连接好像是一条专用线路,而实际上是由数据流传输服务提供的可靠的虚拟连接。 有缓冲的传输:使用虚电路服务来发送数据流的应用程序不断地向协议软件提交以字节为单位的数据,并放在缓冲区中。当累积到足够多的数据时,将它们组成大小合理的数据报,再发送到互联网上传输。这样可提高传输效率,减少网络流量。当应用程序传送特别大的数据块时,协议软件将它们划分为适合于传输的较小的数据块,并且保证在接收端收到的数据流与发送的顺序完全相同。 无结构的数据流: TCP/IP 协议并未区分结构化的数据流。使用数据流服务的应用程序必须在传输数据前就了解数据流的内容,并对其格式进行协商。 全双工连接: TCP/IP 流服务提供的连接功能是双向的,这种连接叫做全双工连接。对一个应用程序而言,全双工连接包括了两个独立的、流向相反的数据流,而且这两个数据流之间不进行显式的交互。全双工连接的优点在于底层协议软件能够在与送来数据流方向相反方向的数据流中传输控制信息,这种捎带的方式降低了网络流量。 TCP 采用一种名为“带重传功能的肯定确认( positive acknowledge with retransmission )”的技术作为提供可靠数据传输服务的基础。这项技术要求接收方收到数据之后向源站回送确认信息 ACK 。发送方对发出的每个分组都保存一份记录,在发送下一个分组之前等待确认信息。发送方还在送出分组的同时启动一个定时器,并在定时器的定时期满而确认信息还没有到达的情况下,重发刚才发出的分组。图 3-5 表示带重传功能的肯定确认协议传输数据的情况,图 3-6 表示分组丢失引起超时和重传。为了避免由于网络延迟引起迟到的确认和重复的确认,协议规定在确认信息中稍带一个分组的序号,使接收方能正确将分组与确认关联起来。



3.3.2 滑动窗口概念

从图 3-5 可以看出,虽然网络具有同时进行双向通信的能力,但由于在接到前一个分组的确认信息之前必须推迟下一个分组的发送,简单的肯定确认协议浪费了大量宝贵的网络带宽。为此, TCP 使用滑动窗口的机制来提高网络吞吐量,同时解决端到端的流量控制。

滑动窗口技术是简单的带重传的肯定确认机制的一个更复杂的变形,它允许发送方在等待一个确认信息之前可以发送多个分组。如图 3-7 所示,发送方要发送一个分组序列,滑动窗口协议在分组序列中放置一个固定长度的窗口,然后将窗口内的所有分组都发送出去;当发送方收到对窗口内第一个分组的确认信息时,它可以向后滑动并发送下一个分组;随着确认的不断到达,窗口也在不断的向后滑动。



图 3-7 (a) 窗口内包括 8 个分组的滑动窗口协议

(b) 收到对 1 号分组的确认信息后,窗口滑动,使得 9 号分组也能被发送

滑动窗口协议的效率与窗口大小和网络接收分组的速度有关。图 3-8 表示了一个窗口大小为 3 的的滑动窗口协议软件的动作示意图。发送方在收到确认之前就发出了三个分组,在收到第一个分组的确认 ACK1 后,又发送了第四个分组。比较图 3-5 和图 3-8 ,就可以看出使用滑动窗口后网络吞吐量的提高。实际上,当窗口大小等于 1 时,滑动窗口协议就等同于简单的肯定确认协议。通过增加窗口大小,可以完全消除网络的空闲状态。在稳定的情况下,发送方能以网络传输分组的最快能力来发送分组。



图 3-8 使用窗口大小为 3 的滑动窗口协议传输分组示例

3.3.3 TCP 报文格式

两台计算机上的 TCP 软件之间传输的数据单元称为报文段。 TCP 通过报文段的交互来建立连接、传输数据、发出确认、通告窗口大小以及关闭连接。 TCP 报文分为两部分,前面是报头,后面是数据。报头的前 20 个字节格式是固定的,后面是可能的选项,数据长度最大为 65535 – 20 – 20 = 65495 字节,其中第一个 20 指 IP 头,第二个 20 指 TCP 头。不带任何数据的报文也是合法的,一般用于确认和控制报文。图 3-9 给出了 TCP 报文的布局格式。每个字段的意义简介如下:

0

31

源端口( source port )号

目的端口( destination port )号

顺序号( sequence number )

确认号( acknowledgement number )

TCP 报头长度

保留

URG

ACK

PSH

RST

SYN

FIN

窗口大小( window size )

校验和( checksum )

紧急指针( urgent pointer )

选项+填充( 0 或多个 32 位字)

数据( 0 或多个字节)

图 3-9 TCP 报头格式

源端口号( 16 位):它(连同源主机 IP 地址)标识源主机的一个应用进程。 目的端口号( 16 位):它(连同目的主机 IP 地址)标识目的主机的一个应用进程。这两个值加上 IP 报头中的源主机 IP 地址和目的主机 IP 地址唯一确定一个 TCP 连接。 顺序号( 32 位):用来标识从 TCP 源端向 TCP 目的端发送的数据字节流,它表示在这个报文段中的第一个数据字节的顺序号。如果将字节流看作在两个应用程序间的单向流动,则 TCP 用顺序号对每个字节进行计数。序号是 32bit 的无符号数,序号到达 2 32 - 1 后又从 0 开始。当建立一个新的连接时, SYN 标志变 1 ,顺序号字段包含由这个主机选择的该连接的初始顺序号 ISN ( Initial Sequence Number )。 确认号( 32 位):包含发送确认的一端所期望收到的下一个顺序号。因此,确认序号应当是上次已成功收到数据字节顺序号加 1 。只有 ACK 标志为 1 时确认序号字段才有效。 TCP 为应用层提供全双工服务,这意味数据能在两个方向上独立地进行传输。因此,连接的每一端必须保持每个方向上的传输数据顺序号。 TCP 报头长度( 4 位):给出报头中 32bit 字的数目,它实际上指明数据从哪里开始。需要这个值是因为任选字段的长度是可变的。这个字段占 4bit ,因此 TCP 最多有 60 字节的首部。然而,没有任选字段,正常的长度是 20 字节。 保留位( 6 位):保留给将来使用,目前必须置为 0 。 控制位( control flags , 6 位):在 TCP 报头中有 6 个标志比特,它们中的多个可同时被设置为 1 。依次为: URG :为 1 表示紧急指针有效,为 0 则忽略紧急指针值。 ACK :为 1 表示确认号有效,为 0 表示报文中不包含确认信息,忽略确认号字段。 PSH :为 1 表示是带有 PUSH 标志的数据,指示接收方应该尽快将这个报文段交给应用层而不用等待缓冲区装满。 RST :用于复位由于主机崩溃或其他原因而出现错误的连接。它还可以用于拒绝非法的报文段和拒绝连接请求。一般情况下,如果收到一个 RST 为 1 的报文,那么一定发生了某些问题。 SYN :同步序号,为 1 表示连接请求,用于建立连接和使顺序号同步( synchronize )。 FIN :用于释放连接,为 1 表示发送方已经没有数据发送了,即关闭本方数据流。 窗口大小( 16 位):数据字节数,表示从确认号开始,本报文的源方可以接收的字节数,即源方接收窗口大小。窗口大小是一个 16bit 字段,因而窗口大小最大为 65535 .. 字节。 校验和( 16 位):此校验和是对整个的 TCP 报文段,包括 TCP 头部和 TCP 数据,以 16 位字进行计算所得。这是一个强制性的字段,一定是由发送端计算和存储,并由接收端进行验证。 紧急指针( 16 位):只有当 URG 标志置 1 时紧急指针才有效。紧急指针是一个正的偏移量,和顺序号字段中的值相加表示紧急数据最后一个字节的序号。 TCP 的紧急方式是发送端向另一端发送紧急数据的一种方式。 选项:最常见的可选字段是最长报文大小,又称为 MSS(Maximum Segment Size) 。每个连接方通常都在通信的第一个报文段(为建立连接而设置 SYN 标志的那个段)中指明这个选项,它指明本端所能接收的最大长度的报文段。选项长度不一定是 32 位字的整数倍,所以要加填充位,使得报头长度成为整字数。 数据: TCP 报文段中的数据部分是可选的。在一个连接建立和一个连接终止时,双方交换的报文段仅有 TCP 首部。如果一方没有数据要发送,也使用没有任何数据的首部来确认收到的数据。在处理超时的许多情况中,也会发送不带任何数据的报文段。

3.4 TCP 连接建立与关闭

TCP 是一个面向连接的协议,无论哪一方向另一方发送数据之前,都必须先在双方之间建立一条连接。本节将详细讨论一个TCP 连接是如何建立的以及通信结束后是如何终止的。

3.4.1 建立一个 TCP 连接

TCP使用三次握手 ( three-way handshake ) 协议来建立连接,图 3-10 描述了三次握手的报文序列。这三次握手为:

请求端(通常称为客户)发送一个 SYN 报文段( SYN 为 1 )指明客户打算连接的服务器的端口,以及初始顺序号( ISN )。 服务器发回包含服务器的初始顺序号的 SYN 报文段( SYN 为 1 )作为应答。同时,将确认号设置为客户的 ISN 加 1 以对客户的 SYN 报文段进行确认( ACK 也为 1 )。 客户必须将确认号设置为服务器的 ISN 加 1 以对服务器的 SYN 报文段进行确认( ACK 为 1 ),该报文通知目的主机双方已完成连接建立。



发送第一个 SYN 的一端将执行主动打开( active open ),接收这个 SYN 并发回下一个 SYN 的另一端执行被动打开( passive open )。另外, TCP 的握手协议被精心设计为可以处理同时打开( simultaneous open ),对于同时打开它仅建立一条连接而不是两条连接。因此,连接可以由任一方或双方发起,一旦连接建立,数据就可以双向对等地流动,而没有所谓的主从关系。

三次握手协议是连接两端正确同步的充要条件。因为 TCP 建立在不可靠的分组传输服务之上,报文可能丢失、延迟、重复和乱序,因此协议必须使用超时和重传机制。如果重传的连接请求和原先的连接请求在连接正在建立时到达,或者当一个连接已经建立、使用和结束之后,某个延迟的连接请求才到达,就会出现问题。采用三次握手协议(加上这样的规则:在连接建立之后 TCP 就不再理睬又一次的连接请求)就可以解决这些问题。

三次握手协议可以完成两个重要功能:它确保连接双方做好传输准备,并使双方统一了初始顺序号。初始顺序号是在握手期间传输顺序号并获得确认:当一端为建立连接而发送它的 SYN 时,它为连接选择一个初始顺序号;每个报文段都包括了顺序号字段和确认号字段,这使得两台机器仅仅使用三个握手报文就能协商好各自的数据流的顺序号。一般来说, ISN 随时间而变化,因此每个连接都将具有不同的 ISN 。

3.4.2 关闭一个 TCP 连接

TCP 连接建立起来后,就可以在两个方向传送数据流。当 TCP 的应用进程再没有数据需要发送时,就发关闭命令。 TCP 通过发送控制位 FIN=1 的数据片来关闭本方数据流,但还可以继续接收数据,直到对方关闭那个方向的数据流,连接就关闭。

TCP 协议使用修改的三次握手协议来关闭连接, 如图 3-11 所示,即终止一个连接要经过 4 次握手。这是因为 TCP 的半关闭( half-close )造成的。由于一个 TCP 连接是全双工(即数据在两个方向上能同时传递),因此每个方向必须单独地进行关闭。关闭的原则就是当一方完成它的数据发送任务后就能发送一个 FIN 来终止这个方向连接。当一端收到一个 FIN ,它必须通知应用层另一端已经终止了那个方向的数据传送。发送 FIN 通常是应用层进行关闭的结果。



从一方的 TCP 来说,连接的关闭有三种情况:

• 本方启动关闭

收到本方应用进程的关闭命令后, TCP 在发送完尚未处理的报文段后,发 FIN = 1 的报文段给对方,且 TCP 不再受理本方应用进程的数据发送。在 FIN 以前发送的数据字节,包括 FIN ,都需要对方确认,否则要重传。注意 FIN 也占一个顺序号。一旦收到对方对 FIN 的确认以及对方的 FIN 报文段,本方 TCP 就对该 FIN 进行确认,在等待一段时间,然后关闭连接。等待是为了防止本方的确认报文丢失,避免对方的重传报文干扰新的连接。

• 对方启动关闭

当 TCP 收到对方发来的 FIN 报文时,发 ACK 确认此 FIN 报文,并通知应用进程连接正在关闭。应用进程将以关闭命令响 应。 TCP 在发送完尚未处理的报文段后,发一个 FIN 报文给对方 TCP ,然后等待对方对 FIN 的确认,收到确认后关闭连接。若对方的确认未及时到达,在等待一段时间后也关闭连接。

• 双方同时启动关闭

连接双方的应用进程同时发关闭命令,则双方 TCP 在发送完尚未处理的报文段后,发送 FIN 报文。各方 TCP 在 FIN 前所发报文都得到确认后,发 ACK 确认它收到的 FIN 。各方在收到对方对 FIN 的确认后,同样等待一段时间再关闭连接。这称之为同时关闭( simultaneous close )。

3.4.3 TCP 状态机

TCP 协议的操作可以使用一个具有 11 种状态的有限状态机( Finite State Machine )来表示,图 3-12 描述了 TCP 的有限状态机,图中的圆角矩形表示状态,箭头表示状态之间的转换,各状态的描述如表 3-2 所示。图中用粗线表示客户端主动和被动的服务器端建立连接的正常过程:客户端的状态变迁用粗实线,服务器端的状态变迁用粗虚线。细线用于不常见的序列,如复位、同时打开、同时关闭等。图中的每条状态变换线上均标有“事件/动作”:事件是指用户执行了系统调用( CONNECT 、 LISTEN 、 SEND 或 CLOSE )、收到一个报文段( SYN 、 FIN 、 ACK 或 RST )、或者是出现了超过两倍最大的分组生命期的情况;动作是指发送一个报文段( SYN 、 FIN 或 ACK )或什么也没有(用“-”表示)。



图 3-12 TCP 有限状态机。粗实线表示客户的正常路径;

粗虚线表示服务器的正常路径;细线表示不常见的事件。

每个连接均开始于 CLOSED 状态。当一方执行了被动的连接原语( LISTEN )或主动的连接原语( CONNECT )时,它便会脱离 CLOSED 状态。如果此时另一方执行了相对应的连接原语,连接便建立了,并且状态变为 ESTABLISHED 。任何一方均可以首先请求释放连接,当连接被释放后,状态又回到了 CLOSED 。

表 3-2 TCP 状态表

状 态

描 述

CLOSED

关闭状态,没有连接活动或正在进行

LISTEN

监听状态,服务器正在等待连接进入

SYN RCVD

收到一个连接请求,尚未确认

SYN SENT

已经发出连接请求,等待确认

ESTABLISHED

连接建立,正常数据传输状态

FIN WAIT 1

(主动关闭)已经发送关闭请求,等待确认

FIN WAIT 2

(主动关闭)收到对方关闭确认,等待对方关闭请求

TIMED WAIT

完成双向关闭,等待所有分组死掉

CLOSING

双方同时尝试关闭,等待对方确认

CLOSE WAIT

(被动关闭)收到对方关闭请求,已经确认

LAST ACK

(被动关闭)等待最后一个关闭确认,并等待所有分组死掉

1. 正常状态转换

我们用图 3-13 来显示在正常的 TCP 连接的建立与终止过程中,客户与服务器所经历的不同状态。读者可以对照图 3-12 来阅读,使用图 3-12 的状态图来跟踪图 3-13 的状态变化过程,以便明白每个状态的变化:

服务器端首先执行 LISTEN 原语进入被动打开状态( LISTEN ),等待客户端连接; 当客户端的一个应用程序发出 CONNECT 命令后,本地的 TCP 实体为其创建一个连接记录并标记为 SYN SENT 状态,然后给服务器发送一个 SYN 报文段; 服务器收到一个 SYN 报文段,其 TCP 实体给客户端发送确认 ACK 报文段同时发送一个 SYN 信号,进入 SYN RCVD 状态; 客户端收到 SYN + ACK 报文段,其 TCP 实体给服务器端发送出三次握手的最后一个 ACK 报文段,并转换为 ESTABLISHED 状态; 服务器端收到确认的 ACK 报文段,完成了三次握手,于是也进入 ESTABLISHED 状态。

在此状态下,双方可以自由传输数据。当一个应用程序完成数据传输任务后,它需要关闭 TCP 连接。假设仍由客户端发起主动关闭连接。

客户端执行 CLOSE 原语,本地的 TCP 实体发送一个 FIN 报文段并等待响应的确认(进入状态 FIN WAIT 1 ); 服务器收到一个 FIN 报文段,它确认客户端的请求发回一个 ACK 报文段,进入 CLOSE WAIT 状态; 客户端收到确认 ACK 报文段,就转移到 FIN WAIT 2 状态,此时连接在一个方向上就断开了; 服务器端应用得到通告后,也执行 CLOSE 原语关闭另一个方向的连接,其本地 TCP 实体向客户端发送一个 FIN 报文段,并进入 LAST ACK 状态,等待最后一个 ACK 确认报文段; 客户端收到 FIN 报文段并确认,进入 TIMED WAIT 状态,此时双方连接均已经断开,但 TCP 要等待一个 2 倍报文段最大生存时间 MSL ( Maximum Segment Lifetime ),确保该连接的所有分组全部消失,以防止出现确认丢失的情况。当定时器超时后, TCP 删除该连接记录,返回到初始状态( CLOSED )。 服务器收到最后一个确认 ACK 报文段,其 TCP 实体便释放该连接,并删除连接记录,返回到初始状态( CLOSED )。



2. 同时打开:

尽管发生的可能性极小,两个应用程序同时彼此执行主动打开的情况还是可能的。每一方必须发送一个 SYN ,且这些 SYN 必须传递给对方。这需要每一方使用一个对方周知的端口作为本地端口。例如,主机 A 中的一个应用程序使用本地端口 7777 ,并与主机 B 的端口 8888 执行主动打开。主机 B 中的应用程序则使用本地端口 8888 ,并与主机 A 的端口 7777 执行主动打开。 TCP 是特意设计为了可以处理同时打开,对于同时打开它仅建立一条连接而不是两条连接(其他的协议族,最突出的是 OSI 传输层,在这种情况下将建立两条连接而不是一条连接)。

当出现同时打开的情况时,状态变迁与图 3-13 所示的不同。两端几乎在同时发送 SYN ,并进入 SYN_SENT 状态。当每一端收到 SYN 时,状态变为 SYN_RCVD ,同时它们都再发 SYN 并对收到的 SYN 进行确认。当双方都收到 SYN 及相应的 ACK 时,状态都变迁为 ESTABLISHED 。图 3-14 显示了这些状态变迁过程。



图 3-14 同时打开期间报文段的交换

一个同时打开的连接需要交换 4 个报文段,比正常的三次握手多一个。此外,要注意的是我们没有将任何一端称为客户或服务器,因为每一端既是客户又是服务器。

3. 同时关闭:

正常情况下都是由一方(通常但不总是客户方)发送第一个 FIN 执行主动关闭,但双方都执行主动关闭也是可能的, TCP 协议也允许这样的同时关闭。

在图 3-12 中,当两端应用层同时发出关闭命令时,两端均从 ESTABLISHED 变为 FIN_WAIT_1 。这将导致双方各发送一个 FIN ,两个 FIN 经过网络传送后分别到达另一端。收到 FIN 后,状态由 FIN_WAIT_1 变迁到 CLOSING ,并发送最后的 ACK 。当收到最后的 ACK 时,状态变化为 TIME_WAIT 。图 3-15 总结了这些状态的变化,从图中可以看出同时关闭与正常关闭使用的报文段交换数目相同。



图 3-15 同时关闭期间的报文段交换

4. 其它情况:

服务方打开:从 LISTEN 到 SYN_SENT 的变迁是正确的,它由服务器端主动发出 SYN 报文段,但 Berkeley 版的 TCP 软件并不支持它。 重置连接(复位):只有当 SYN_RCVD 状态是从 LISTEN 状态(正常情况)进入,而不是从 SYN_SENT 状态(同时打开)进入时,从 SYN_RCVD 回到 LISTEN 的状态变迁才是有效的。这意味着如果我们执行被动打开(进入 LISTEN ),收到一个 SYN ,发送一个带 ACK 的 SYN (进入 SYN_RCVD ),然后收到一个 RST ,而不是一个 ACK ,便又回到 LISTEN 状态并等待另一个连接请求的到来。 快速关闭:在主动关闭后的 FIN_WAIT_1 状态,如果收到的报文段不仅是 ACK ,而且还包括对方的 FIN 信号,则直接进入 TIME_WAIT 状态,给对方发送 ACK 报文段,然后等待超时。

另外, TIME_WAIT 状态的等待超时需要再详细解释一下,因为它直接影响到网络应用程序的表现。

每个具体 TCP 实现必须选择一个报文段最大生存时间 MSL ( Maximum Segment Lifetime ),它是任何报文段被丢弃前在网络内的最长时间。我们知道这个时间是有限的,因为 TCP 报文段以 IP 数据报在网络内传输,而 IP 数据报有限制其生存时间的 TTL 字段。 RFC 793 [Postel 1981c ] 指出 MSL 为 2 分钟。然而,实现中的常用值是 30 秒、 1 分钟、或 2 分钟。

对一个具体实现所给定的 MSL 值,处理的原则是:当 TCP 执行一个主动关闭,并发回最后一个 ACK ,该连接必须在 TIME_WAIT 状态停留的时间为 2 倍的 MSL ,因此 TIME_WAIT 状态也称为 2MSL 等待状态。在这段时间内,如果最后的 ACK 丢失,对方会超时并重发最后的 FIN ,这样本地 TCP 可以再次发送 ACK 报文段(这也是它唯一可以发送的报文,并重置 2MSL 定时器)。

这种 2MSL 等待的另一个结果是这个 TCP 连接在 2MSL 等待期间,定义这个连接的套接字( socket ,客户的 IP 地址和端口号,服务器的 IP 地址和端口号)不能再被使用。这个连接只能在 2MSL 结束后才能再被使用。在连接处于 2MSL 等待时,任何迟到的报文段将被丢弃。

我们假设图 3-12 中是客户执行主动关闭并进入 TIME_WAIT ,这是正常的情况,因为服务器通常执行被动关闭,不会进入 TIME_WAIT 状态。这暗示如果我们终止一个客户程序,并立即重新启动这个客户程序,则这个新客户程序将不能重用相同的本地端口。这不会带来什么问题,因为客户使用本地端口,而并不关心这个端口号是什么。然而,对于服务器,情况就有所不同,因为服务器使用周知端口。如果我们终止一个已经建立连接的服务器程序,并试图立即重新启动这个服务器程序,服务器程序将不能把它的这个周知端口赋值给它的端点,因为那个端口是处于 2MSL 连接的一部分。在重新启动服务器程序前,它需要在 1~4 分钟。这就是很多网络服务器程序被杀死后不能够马上重新启动的原因(错误提示为“ Address already in use ”)。

3.5 小结

和 IP 一样, TCP 也是 TCP/IP 协议簇中最为重要的协议。本章详细地介绍了 TCP 的工作原理、数据报格式,特别是 TCP 连接建立与关闭的状态转换。由于 TCP 是离应用层最近的底层协议,因此 TCP 的很多状态在上层应用中是可见的,在后面的章节中,很多地方都涉及到 TCP 的各种状态。因此,掌握本章介绍的原理和概念,对于学好后面的章节极为有利,特别是掌握了 TCP 的状态转换规律,对于网络的配置与诊断、以及网络应用的调试大有裨益。

习 题

什么是周知端口?不看前面的表格,说说你常用的网络服务所用到的 TCP 和 UDP 周知端口号。 试着在你的本地网络环境上使用 UDP ,对长度分别为 256 、 512 、 1024 、 2048 、 4096 和 8192 字节的报文测试其平均传输速率。请解释得到的结果(提示:你的网络的 MTU 值是多少?)。 UDP 协议很简单,那为什么还需要设置它?直接让用户进程发送原始的 IP 分组还不够吗? TCP 和 UDP 分别提供什么样的传输服务?为什么说它们提供进程之间的通信服务?它们如何区分建立在其上的应用进程? 主机 A 的一个进程被赋予端口 p ,主机 B 的一个进程被赋予端口 q 。有可能在这两个端口之间同时存在两个或多个连接吗?为什么? TCP 传输服务的可靠性是如何保证的? 什么是 TCP 连接建立的三次握手?为什么需要三次握手? 叙述一下进入图 3-12 中 SYN_RCVD 状态的两种途径。 根据 TCP 的有限状态机,请仔细分析描述两个地点的主机分别使用主动和被动打开方式和使用三次握手的过程。 根据 TCP 状态的转换,请仔细研究两个机器同意关闭连接的状态转换过程。 思考一下,为什么 TCP 在 TIME_WAIT 状态要设置等待 2MSL 超时,而在 LAST_ACK 状态不设置? 获取 RFC 793 ,阅读并理解 TCP 协议。

二 : 传输控制协议

传输控制协议
(Transmission Control Protocol, TCP)
目录
引言
1. TCP协议的简介
2. TCP协议的重要性与及在网络层次中的关系
3. TCP在其网络环境的工作原理(重点内容)
3.1 TCP工作原理概述
3.2 TCP工作的具体过程
3.3. 序列号
3.5. 关闭连接
3.6. 优先和安全
3.7. 数据通信
3.8. 接口
3.9. 事件处理
4. 结束语
关键词: 序列号. 接口 . 连接. 事件
引言
网络中不同的工作站,服务器之间能传输数据,源于协议的存在。随着网络的发展,不同的开发商开发了不同的通信方式。为了使通信成功可靠,网络中的所有主机都必须使用同一语言,不能带有方言。因而必须开发严格的标准定义主机之间的每个包中每个字中的每一位。这些标准来自于多个组织的努力,约定好通用的通信方式,即协议。这些都使通信更容易。然而只有少数被保留了下来。每种网络协议都有自己的优点,但是只有TCP允许与Internet完全的连接。TCP是在60年代由麻省理工学院和一些商业组织为美国国防部开发的,即便遭到核攻击而破坏了大部分网络,TCP仍然能够维持有效的通信,所以有
必要去了解它。
一、TCP协议简介
TCP是一个面向连接的传输层协议,虽然TCP不属于ISO制定的协议集,但由于其在商业界和工业界的成功应用,它已成为事实上的网络标准,广泛应用于各种网络主机间的通信。
作为一个面向连接的传输层协议,TCP的目标是为用户提供可靠的端到端连接,保证信息有序无误的传输。它除了提供基本的数据传输功能外,还为保证可靠性采用了数据编号、校验和计算、数据确认等一系列措施。它对传送的每个数据字节都进行编号,并请求接收方回传确认信息(ACK)。发送方如果在规定的时间内没有收到数据确认,就重传该数据。数据编号使接收方能够处理数据的失序和重复问题。数据误码问题通过在每个传输的数据段中增加校验和予以解决,接收方在接收到数据后检查校验和,若校验和有误,则丢弃该有误码的数据段,并要求发送方重传。流量控制也是保证可靠性的一个重要措施,若无流控,可能会因接收缓冲区溢出而丢失大量数据,导致许多重传,造成网络拥塞恶性循环。TCP采用可变窗口进行流量控制,由接收方控制发送方发送的数据量。
TCP为用户提供了高可靠性的网络传输服务,但可靠性保障措施也影响了传输效率。因此,在实际工程应用中,只有关键数据的传输才采用TCP,而普通数据的传输一般采用高效率的UDP。
二、TCP协议的重要性与及在网络层次中的关系
TCP协议主要为了在主机间实现高可靠性的包交换传输协议。计算机网络在现代社会中已经是不可缺少的了,TCP协议主要在网络不可靠的时候完成通信,对军方可能特别有用,但是对于政府和商用部门也适用。TCP是面向连接的端到端的可靠协议。它支持多种网络应用程序。TCP对下层服务没有多少要求,它假定下层只能提供不可靠的数据报服务,它可以在多种硬件构成的网络上运行。下面的图是TCP在层次式结构中的位置,它的下层是IP协议,TCP可以根据IP协议提供的服务传送大小不定的数据,IP协议负责对数据进行分段,重组,在多种网络中传送。

TCP的上面就是应用程序,下面是IP协议,上层接口包括一系列类似于操作系统中断的调用。对于上层应用程序来说,TCP应该能够异步传送数据。下层接口我们假定为IP协议接口。为了在并不可靠的网络上实现面向连接的可靠的传送数据,TCP必须解决可靠性,流量控制的问题,必须能够为上层应用程序提供多个接口,同时为多个应用程序提供数据,同时TCP必须解决连接问题,这样TCP才能称得上是面向连接的,最后,TCP也必须能够解决通信安全性的问题。
三、TCP在其网络环境的工作原理(重点内容)
3.1 TCP工作原理概述
网络环境包括由网关(或其它设备)连接的网络,网络可以是局域网也可以是一些城域网或广域网,但无论它们是什么,它们必须是基于包交换的。主机上不同的协议有不同的端口号,一对进程通过这个端口号进行通信。这个通信不包括计算机内的I/O操作,只包括在网络上进行的操作。网络上的计算机被看作包传送的源和目的结点。特别应该注意的是:计算机中的不同进程可能同时进行通信,这时它们会用端口号进行区别,不会把发向A进程的数据由B进程接收的。
进程为了传送数据会调用TCP,将数据和相应的参数传送给TCP,于是TCP会将数据传送到目的TCP那里,当然这是通过将TCP包打包在IP包内在网络上传送达到的。接收方TCP在接收到数据后会通信上层应用程序,TCP会保证接收数据顺序的正确性[www.61k.com)。虽然下层协议可能不会保证顺序是正确的。这里需要说明的是网关在接收到这个包后,会将包解开,看看是不是已经到目的地了,如果没有到,应该走什么路由达到目的地,在决定后,网关会根据下一个网络内的协议情况再次将TCP包打包传送,如果需要,还要把这个包再次分成几段再传送。这个落地检查的过程是一个耗时的过程。从上面,我们可以看出TCP传送的基本过程,当然具体过程可能要复杂得多。
3.2 TCP工作的具体过程
在实现TCP的主机上,TCP可以被看成是一个模块,和文件系统区别不大,TCP也可以调用一些操作系统的功能,TCP不直接和网络打交道,控制网络的任务由专门的设备驱动模块完成。TCP只是调用IP接口,IP向TCP提供所有TCP需要的服务。通过下图我们可以更清楚地看到TCP协议的结构。

上面已经说过了,TCP连接是可靠的,而且保证了传送数据包的顺序,保证顺序是用一个序号来保证的。响应包内也包括一个序列号(请看3.3具体介绍序列号),表示接收方准备好这个序号的包。在TCP传送一个数据包时,它同时把这个数据包放入重发队列中,同时启动记数器,如果收到了关于这个包的确认信息,将此包从队列中删除,如果计时超时则需要重新发送此包。请注意,从TCP返回的确认信息并不保证最终接收者接收到数据,这个责任由接收方负责。
每个用于传送TCP的通道都有一个端口标记,因为这个标记是由每个TCP终端确定的,因此TCP可能不唯一,为了保证这个数值的唯一,要使用网络地址和端口号的组合达到唯一标识的目的,我们称这个为了套接字(Socket),一个连接由连接两端的套接字标识,本地的套接字可能和不同的外部套接字通信,这种通信是全双工的。
通过向本地端口发送OPEN命令及外部套接字参数建立连接,TCP返回一个标记这个连接的名称,以后如果用户需要使用这个名称标记这个连接。为了保存这个连接的信息,我们假设有一个称为传输控制块(Transmission Control Block,TCB)的东西来保存。OPEN命令还指定这个连接的建立是主动请求还是被动等待请求。下面我们要涉及具体的功能了,TCP段以internet数据报的形式传送。IP包头传送不同的信息域,包括源地址和目的地址。TCP头跟在internet包头后面,提供了一些专用于TCP协议的信息。下图是TCP包头格式图:

源端口:16位;
目的端口:16位
序列码:32位,当SYN出现,序列码实际上是初始序列码(ISN),而第一个数据字节是ISN+1;
确认码:32位,如果设置了ACK控制位,这个值表示一个准备接收的包的序列码;
数据偏移量:4位,指示何处数据开始;
保留:6位,这些位必须是0;
控制位:6位;
窗口:16位;
校验位:16位;
优先指针:16位,指向后面是优先数据的字节;
选项:长度不定;但长度必须以字节记;选项的具体内容我们结合具体命令来看;
填充:不定长,填充的内容必须为0,它是为了保证包头的结合和数据的开始处偏移量能够被32整除;

我们前面已经说过有一个TCB的东西了,TCB里有存储了包括发送方,接收方的套接字,用户的发送和接收的缓冲区指针等变量。除了这些还有一些变量和发送接收序列号有关:
发送序列变量
SND.UNA 发送未确认
SND.NXT 发送下一个
SND.WND 发送窗口
SND.UP 发送优先指针
SND.WL1 用于最后窗口更新的段序列号
SND.WL2 用于最后窗口更新的段确认号
ISS 初始发送序列号

接收序列号
RCV.NXT 接收下一个
RCV.WND 接收下一个
RCV.UP 接收优先指针
IRS 初始接收序列号
下图会帮助您了解发送序列变量间的关系:
当前段变量
SEG.SEQ 段序列号
SEG.ACK 段确认标记
SEG.LEN 段长
SEG.WND 段窗口
SEG.UP 段紧急指针
SEG.PRC 段优先级
连接进程是通过一系列状态表示的,这些状态有:LISTEN,SYNSENT,SYNRECEIVED,ESTABLISHED,FINWAIT1,FINWAIT2,CLOSEWAIT,CLOSING,LASTACK,TIMEWAIT和 CLOSED。CLOSED表示没有连接,各个状态的意义如下:
LISTEN 侦听来自远方TCP端口的连接请求;
SYNSENT 在发送连接请求后等待匹配的连接请求;
SYNRECEIVED 在收到和发送一个连接请求后等待对连接请求的确认;
ESTABLISHED 代表一个打开的连接,数据可以传送给用户;
FINWAIT1 等待远程TCP的连接中断请求,或先前的连接中断请求的确认;
FINWAIT2 从远程TCP等待连接中断请求;
CLOSEWAIT 等待从本地用户发来的连接中断请求;
CLOSING 等待远程TCP对连接中断的确认;
LASTACK 等待原来发向远程TCP的连接中断请求的确认;
TIMEWAIT 等待足够的时间以确保远程TCP接收到连接中断请求的确认;
CLOSED 没有任何连接状态;
TCP连接过程是状态的转换,促使发生状态转换的是用户调用:OPEN,SEND,RECEIVE,CLOSE,ABORT和STATUS;传送过来的数据段,特别那些包括以下标记的数据段SYN,ACK,RST和FIN;还有超时,上面所说的都会时TCP状态发生变化。

下面的图表示了TCP状态的转换,但这图中没有包括错误的情况和错误处理,不要把这幅图看成是总说明了。

3.3. 序列号
请注意,我们在TCP连接中发送的字节都有一个序列号。因为编了号,所以可以确认它们的收到。对序列号的确认是累积性的,也就是说,如果用户收到对X的确认信息,这表示在X以前的数据(不包括X)都收到了。在每个段中字节是这样安排的:第一个字节在包头后面,按这个顺序排列。我们需要认记实际的序列空间是有限的,虽然很大,但是还是有限的,它的范围是0到2的32次方减1。我想熟悉编程的一定知道为什么要在计算两个段是不是相继的时候要使用2的32次方为模了。TCP必须进行的序列号比较操作种类包括以下几种:
(a) 决定一些发送了的但未确认的序列号;
(b) 决定所有的序列号都已经收到了;
(c) 决定下一个段中应该包括的序列号。
对于发送的数据TCP要接收确认,处理确认时必须进行下面的比较操作:
SND.UNA = 最老的确认了的序列号;
SND.NXT = 下一个要发送的序列号;
SEG.ACK = 接收TCP的确认,接收TCP期待的下一个序列号;
SEG.SEQ = 一个数据段的第一个序列号;
SEG.LEN = 数据段中包括的字节数;
SEG.SEQ+SEG.LEN1 = 数据段的最后一个序列号。
请注意下面的关系:
SND.UNA < SEG.ACK =< SND.NXT
如果一个数据段的序列号小于等于确认号的值,那么整个数据段就被确认了。而在接收数据时下面的比较操作是必须的:
RCV.NXT = 期待的序列号和接收窗口的最低沿;
RCV.NXT+RCV.WND1 = 最后一个序列号和接收窗口的最高沿;
SEG.SEQ = 接收到的第一个序列号;
SEG.SEQ+SEG.LEN1 = 接收到的最后一个序列号;

上面几个量有如下关系:
RCV.NXT =< SEG.SEQ < RCV.NXT+RCV.WND 或 RCV.NXT =< SEG.SEQ+SEG.LEN1 < RCV.NXT+RCV.WND
测试的第一部分是检查数据段的开始部分是否在接收窗口中,第二部分是检查数据段的结束部分是否也在接收窗口内;上面两个检查通过任何一个就说明它包括窗口要求的数据。实际中的情况会更复杂一些,因为有零窗口和零数据段长,因此我们有下面四种情况:
段长度接收窗口测试
00SEG.SEQ = RCV.NXT
0>0RCV.NXT =< SEG.SEQ < RCV.NXT+RCV.WND
>00不可接受
>0>0RCV.NXT =< SEG.SEQ < RCV.NXT+RCV.WND或RCV.NXT =< SEG.SEQ+SEG.LEN1 < RCV.NXT+RCV.WND
请注意接收窗口的大小可以为零,在窗口为零时它只用来接收ACK信息,因此对于一个TCP来说,它可以使用零大小窗口在发送数据的同时接收数据。即使接收窗口的大小为零,TCP必须处理所有接收到信息的RST和URG域。
我们也应用计数的方式保护了一些特定的控制信息,这是通过隐式地使用一些控制标记使数据段能够可靠地重新发送(或确认)为达到的。控制信息并不在段数据空间中传送,因此,我们必须采用隐式指定序列号进行控制。SYN和FIN是需要保护的控制量,这两个控制量也只在连接打开和关闭时使用。SYN被认为是在第一个实际数据之间的数据,而FIN是最后一个实际数据之后的数据。段长度(SEG.LEN)包括数据和序列号空间,如果出现了SYN,那么SEG.SEQ是SYN的序列号。
初始序列号选择
协议对于特定连接被重复使用没有什么限制。连接是由一对套接字定义的。新的连接实例被定义为连接的另一次恢复,这就带来了问题:TCP如果确定多个数据段是从以前连接的另一次恢复中取得的呢?这个问题在连接迅速打开和关闭,或因为内存原因被关闭然后又迅速建立后显示特别突出。
为了避免混乱,用户必须避免因此恢复使用某一连接,而使序列号发生混乱。我们必须保证序列号的正确性,即使TCP失败,根本不知道以前的序列号是什么的情况下也要保证序列号的正确性。当新的连接被创建时,产生一个新的初始序列号(ISN)产生子,它用来选择一个新的32位ISN。产生子和32位时钟的低度位字节相关,低位字节的刷新频率大概是4微秒,因此ISN的循环时间大概是4.55小时。因此我们把网络包的最长生存时间(MSL)小于4.55小时,因此我们可以认为ISN是唯一的。对于每个连接都有发送序列号和接收序列号,初始发送序列号(ISS)由发送TCP选择,而初始接收序列号是在连接建立过程中产生的。
对于将要连接或初始化的连接,两个TCP必须和对方的初始序列号同步。这通过交换一个控制位SYN和初始序列号完成。我们把带有SYN的数据段称为"SYNs"。同步的获得过程这里就不重复了,每方必须发送自己的序列号并返回对对方序列号的确认。
1) A > B SYN 本方序列号是X
2) A < B ACK 本方序列号被确认
3) A < B SYN 对方序列号是Y
4) A > B ACK 确认对方序列号
上面的第2步和第3步可以合并,这时可以成为3阶段,所以我们可以称它为三消息握手。这个过程是必须的,因为序列号不和全局时钟关联,TCP也可以有不同的机制选择ISN。接收到第一个SYN的接收方不可能知道这个数据段是不是被延时,除非它记住了在连接上使用的最近的序列号(这通常是不可能的),因此它必须要求发送者确认。
为了保证TCP获得的确认是刚才发送的段产生的,而不是仍然在网络中的老数据段产生的,因此TCP必须在MSL时间之内保持沉默。在本文中,我们假设MSL=2小时,这是出于工程的需要,如果用户觉得可以,他可以改变MSL。请注意如果TCP重新初始化,而内存中的序列号正在使用,不需要等待,但必须确认使用的序列号比当前使用的要大。
如果一台主机在未保留任何序列号的情况下失败,那么它应该在MSL时间之内不发出任何数据段。下面将会这一情况进行说明。TCP的实现可以不遵守这个规定,但是这会造成老数据被当成新数据接收,而新数据被当成老数据拒绝的情况。
每当数据段形成并进入输出队列,TCP会为它指定序列空间中的一个值。TCP中多复本检测和序列算法都依赖于这个地址空间,在对方发送或接收之前不会超过2的32次方个包存在于输出队列中。所有多余的数据段都会被删除。如果没有这个规定,会出现多个数据段被指定同一个序列号的情况,会造成混乱。数据段中序列号的多少和数据段中的字节数一样多。
在通常情况下,TCP保留下一个要发送的序列号和还未确认的最老的序列号,不要在没有确认的时候就再次使用,这样会有些风险,也正是因为这样的目的,所以序列空间很大。对于2M的网络,要4.5小时来耗尽序列空间,因为一个数据段可能的最大生存时间也不过十几分之一秒,这就留下了足够的空间;而在100M的网络上需要5.4分钟,虽然少了点,但也可以了。
如果在实现TCP时没有为保存序列号留下空间,那清除多余的包可能就不能实现了,因此推荐这种类型的TCP实现最好在失败后等待MSL时间,这样保证多余的包被删除。这种情况有时候也可能会出现在保留序列号的TCP实现中。如果TCP在选择一个另一个TCP连接正在使用的序列号时,这台主机突然失败了,这就产生了问题。这个问题的实质在于主机不知道它失败了多久,也不知道多余的复本是不是还在网络中。
处理这种问题的方法是等待MSL时间,如果不这样就要冒着对方错误接收数据的危险,要等待的时间也就称为“沉默时间”。实现者可以让用户选择是不是等待,但是无论用户如何也不见得非要等待MSL时间。
3.4. 建立一个连接
建立连接应用的是三消息握手。如果双方同时都发送SYN也没有关系,双方会发现这个SYN中没有确认,于是就知道了这种情况,通常来说,应该发送一个"reset"段来解决这种情况。三消息握手减少了连接失败的可能性。下面就是一个例子,在尖括号是的就是数据段中的内容和标记。其它的就不多说了。

在第2行,TCP A发送SYN初始化序列号,表示它要使用序列号100;第3行中,TCP B给出确认,并且期待着A的带有序列号101的数据段;第4行,TCP A给出确认,而在第5行,它也给出确认,并发送了一些数据,注意第4行的序列号与第5号的一样,因为ACK信息不占用序列号空间内的序列号。同时产生请求的情况如下图所示,只复杂一点。

使用三消息握手的主要原因是为了防止使用过期的数据段。为了这个目的,必须引入新的控制消息,RESET。如果接收TCP处理非同步状态,在接收到RESET后返回到LISTEN状态。如果TCP处理下面几种状态ESTABLISHED,FINWAIT1,FINWAIT2,CLOSEWAIT,CLOSING,LASTACK,TIMEWAIT时,放弃连接并通过用户。我们下面就详细说明后一种情况。

通过上面的例子,我们可以看出TCP连接是如何从过期数据段的干扰下恢复的。请注意第4行和第5行中的RST(RESET信号)。
半开连接和其它非正常状态
如果一方在未通过另一方的情况下关闭连接,或双方虽然失败而不同步的情况我们称为半开连接状态。在一方试图发送数据时连接会自动RESET。然而这种情况毕竟属于不正常情况。应该做出相应的处理。如果A处的连接已经关闭,B处并不知道。当B希望发送数据到A时,就会收到RESET信号,表示这个TCP连接有误,要中止当前连接。
假设A和B两个进程相互通信的时候A的TCP发生了失败,A依靠操作系统支持TCP的存在,通常这种情况下会有恢复机制起作用,当TCP重新恢复的时候,A可能希望从恢复点开始工作。这样A可能会试图OPEN连接,然后在这个它认为还是打开的连接上传送数据,这时A会从本地(也就是A的)TCP上获得错误消息“未打开连接”。A的TCP将发送包括SYN的数据段。下面的例子将显示这一过程:

上面这个例子中,A方收到的信息并没有确认任何东西,这时候A发现出了问题,于是发送了RST控制信息。另一种情况是发生在A失败,而B方仍然试图发送数据时,下面的例子可以表示这种情况,请注意第2行中A对B发送来的信息不知所云。

在下面的例子中,A方和B方进行的被动连接,它们都在等待SYN信息。过期的包传送到B方使B回应了,而收到回应的A却发现不对头,传送RST控制信息,B方返回被动LISTEN状态。

现实中的情况太多了,我们列举一些产生RST控制信息的规则如下:通常情况下,RST在收到的信息不是期待的信息时产生。如果在不能确定时不要轻易发送RST控制信息。下面有三类情况:
1.如果连接已经不存在,而发送来的消息又不是RST,那么要返回RST。如果想拒绝对不存在的连接进行SYN,可以使用这种办法。如果到达的信息有一个ACK域,返回的RST信息可以从ACK域中取得序列号,如果没有这个域,就把RST的序列号设置为0,ACK域被设备为序列号和到达段长度之和。连接仍然处于CLOSE状态。
2.如果连接处于非同步状态(LISTEN,SYNSENT,SYNRECEIVED),而且收到的确认是对未发出包的确认或是接收到数据段的安全级别与不能连接要求的相一一致时,就发送RST。如果SYN未被确认时,而且收到的数据段的优先级比要求的优先级要高,那么要么提高本地优先级(得事先征得用户和系统的许可)要么发送RST;如果接收数据段的优先级比要求的优先级低,就算是匹配了,当然如果对方发现优先级不对提高了优先级,在下一个包中提高了优先级,这就不算是匹配了。如果连接已经进入SYN,那么接收到数据段的优先级必须和本地优先级一样,否则发送RST。如果到达的信息有一个ACK域,返回的RST信息可以从ACK域中取得序列号,如果没有这个域,就把RST的序列号设置为0,ACK域被设备为序列号和到达段长度之和。连接仍然处于与原来相同的状态。
3.如果连接处于同步状态(ESTABLISHED,FINWAIT1,FINWAIT2,CLOSEWAIT,CLOSING,LASTACK,TIMEWAIT),任何超出接收窗口的序列号的数据段都产生如下结果:发出一个空确认数据段,此段中包括当前发送序列号,另外还包括一个确认指出希望接收的下一个数据段的序列号,连接仍然保存在原来的状态。如果因为安全级,优先级之类的问题,那就发送RST信号然后进入CLOSED状态。
RST过程
除了SYNSENT状态外的其它状态中,所有的RST数据段可以通过检查SEQ域查明。如果序列号在接收窗口中,RST是有效的。当连接处于SYNSENT状态时,如果ACK域确认SYN,那么RST也是合法的。
RST的接收方首先确认它的合法性,然后进行状态转换。如果接收方处于LISTEN状态,它就忽略RST包。如果接收方处于SYNRECEIVED状态,而且以前处于LISTEN状态,接收方返回LISTEN状态,否则接收方关闭连接进入CLOSED状态。当接收方处于其它状态时,直接关闭连接回到CLOSED状态。

3.5. 关闭连接
CLOSE是一个操作,它的意思就是“本方已经有数据发送”。由于是全双工的,所以会造成一些麻烦,因为接收方对于处理接收方的连接有点麻烦。我们以一种简单的方式对待CLOSE,发送CLOSE的一方在接收到对方的CLOSED之前,还要继续接收数据。因此程序可以在一个CLOSE之后初始化几个SEND,然后开始RECEIVE,直到接收到对方的CLOSED而RECEIVE失败为止。我们假设TCP可以通知用户连接关闭,即使仍在RECEIVE也可以,这样用户就可以正常关闭了。这样,TCP可以在连接关闭前可靠地发送数据。下面列举了三种基本情况:
情况1:本地用户关闭
这种情况下,可以建立一个FIN段放入发送队列。TCP不再接收用户的SEND指令,TCP进入FINWAIT1状态。RECEIVE在这种状态下是允许的。所有数据段和FIN在未接收到确认以前会一直发送。当另一个TCP确认FIN,并发送自己的FIN后,本地的TCP可以确认这个FIN了。请注意,TCP也可以在确认FIN时不返回自己的FIN,直到用户关闭连接时再返回自己的FIN。
情况2:TCP从网络上接收到一个FIN
如果在没有请求的情况下收到FIN,TCP可以返回ACK并通知用户连接已经关闭。用户可以以CLOSE响应,TCP在发送完剩下的数据后发送自己的FIN,然后TCP等待对这个FIN的确认,在接收到后,它关闭连接。如果确认超时,可以关闭连接并通知用户完事。
情况3:双方同时关闭
双方同时关闭会导致交换FIN。双方会在收到对自己FIN的确认后关闭连接。

3.6. 优先和安全
TCP的操作必须在两个优先级相同的端口间进行。TCP使用的优先和安全参数在IP协议中定义。我们这里所说的安全/间隔就是指的IP中定义的优先,用户组和处理规定。如果不符合则发送RST。这些内容请大家看上一节中的叙述。TCP在操作过程中也会检查接收数据段的优先级,还可以在操作中提高优先级。虽然运行在无安全环境中,主机也必须能够处理安全参数。
3.7. 数据通信
建立了连接以后就是传送数据了,TCP通过重新传送保证每个数据段到达对方,因为有了重新传送,所以对方可能接收到两个相同的包,那就必须根据内部的序列号判断哪个数据段是可以接收的。发送方通过使用SND.NXT跟踪下一个要发送的数据段,而接收方则跟踪RCV.NXT来知道下一个要接收的数据段。发送方要还未确认的最老的序列号保存于SND.UNA。
当发送方形成数据段并发送它后SND.NXT增大;当接收方接收到数据段后RCV.NXT增大并发送确认;当发送方接收到确认后SND.UNA增大。它们三者在不同的时间增大,这是因为传送时延造成的。而增大多少则由数据段中数据的大小决定。注意:连接进入ESTABLISHED状态后,所有的段必须包括当前的确认信息。而CLOSE用户操作的性质类型于推操作,这和在接收到的数据段中的FIN标记一样。
重传超时
因为网络中有不类型的网络,而使用TCP的范围又很广,因此重传超时必须动态决定。下面给出一个例子,通过例子可以看出确定重传超时的过程。下面有两个变量说明时延的问题,一个是环路时间(RTT),它是由一个序列码得到的,这个序列码在发送时给出,在接收到确认时被覆盖;另一个平滑环路时间(SRTT):
SRTT = ( ALPHA * SRTT ) + ((1ALPHA) * RTT)
通过上面的式子,可以得到重传超时(RTO):
RTO = min[UBOUND,max[LBOUND,(BETA*SRTT)]]
其中UBOUND是超时的上界(如1分钟),LBOUND是超时的下界(如1秒钟),ALPHA是平滑因子(如0.8到0.9),BETA是延时变量(如1.3到2.0)。
传送紧急消息
TCP的紧急机制是允许发送者使接收者接收一些紧急消息,并让接收方在接收到这一消息后立刻通知用户。这种机制是在数据流是加入一个点,指出这是紧急数据的结束点,当接收方要接收到这个点之前,它会通知用户进入紧急状态,在接收到这个点的数据后,它会通知用户进入通常状态。如果这个紧急点在用户进入紧急状态时更新,这个更新必须对用户透明。
应用一个紧急域的方法可以达到上述目的,而URG控制标记则指明紧急域是否被使用,而且在数据段中必须加入指示紧急点的序列号,如果没有这个标记则说明没有紧急点。如果需要发送紧急数据,发送方必须起码发送一个字节。
管理窗口
如果我们学习过网络基础,我们一定知道有一个窗口协议,TCP中每个数据段都包括下一个希望接收到的序列号。窗口比较大会提高传送速度,如果传送过来的数据超过的窗口大小,数据会被抛弃。这样会加重网络负担。如果TCP开始时的接收窗口比较大,而到最后这个窗口缩小了,这种作法可不是好办法。对于健壮的TCP来说,最好不要自己缩小窗口,但要做要准备对方的TCP缩小窗口。
即使发送窗口大小为零,发送TCP也必须做好准备接收数据并且可以发送至少一位新数据。即使接收窗口为零,发送方也会重发,重发间的间隔时间一般为两分钟。当接收TCP的接收窗口为零时,在它接收到数据时,它依然会返回确认,其中包括希望收到的序列码和当前窗口大小(为零)。
发送TCP将数据打成符合当前大小的包,但在重新传送队列中可能重新打包。这种重新打包并不是必须的,但是会很有好处。如果一个连接只有单向数据流,窗口信息可以在确认信息中得到,这些的序列号都是一个,因此没法区别出谁先谁后。但这并不是一个严重的问题。改进的方法是在数据段中加入最新的期待序列号,这样就可以区别出谁先谁后了。窗口管理对传送效率有很大影响,下面是一些建议:
当使用更少的大数据而要获得高效率时分配非常小的窗口使数据以许多小段传送。对于发送者来说要避免在发送小数据段时必须等到窗口大到一定程度再进行。确认不要被延时。接收窗口如果大小为零时,要传送的数据段可能被分成越来越小的段。如果发送TCP仅仅发送窗口允许大小的数据段,可能这些数据段会被换成比这个段大(或者小)的数据段发送。接收方时不时地进行窗口大小调整会使大数据段分为小段,而不成对。尽量把小的窗口合成大的窗口。
3.8. 接口
网络协议的分层结构决定了TCP有两个接口,向上的用户接口和下面的接口。对下层接收口的描述不是很清楚,这个工作由下层协议来描述,但是这里我们也描述一些TCP要使用要的参数。
用户/TCP接口
下面描述一些TCP命令,这些命令是功能性的,因各系统不同具体实现可能不同。最后,我们必须清楚,不同的TCP实现可能有不同的用户接口,但是有一些功能是最基本的,本节描述的功能便是这个基本功能集。
TCP用户命令
下面定义的命令与其它高级语言中定义的方法差不多,但有些陷井操作需要的,如SVC,UUO,EMT。下面只是一个功能介绍,具体实现可能大为不同,如有些系统会把这里的多条命令结合成一条命令使用。为了实现通信功能,TCP不能只会接收命令,而且能够返回消息给它服务的进程,这些消息包括:
(a) 关于连接的通常消息,如中断,远程关闭等等;
(b) 对用户命令做出应答,是成功还是失败。
Open
格式:OPEN (local port, foreign socket, active/passive [, timeout] [, precedence] [, security/compartment] [, options]) > local connection name
我们假定本地TCP注意到它所服务的进程标记,而且将检查进程的认证。因实现不同,本地网络和源地址的TCP认证可能由TCP进行也可以由下层协议进行(如IP协议)。这些考虑主要是基于安全性的考虑。
如果active/passive标记设置为passive,TCP会检测到达的连接请求,它是被动的,被动的连接可以有一个完全指定的外套接字用于等待特定的连接或未指定的外套接字来等待任何呼叫。一个完全定义的被动呼叫可以通过执行一系列的SEND命令而变为主动的。创建一个传输控制块(TCB),其中一部分参数是由OPEN命令参数而来。在主动OPEN时,TCP会立刻开始同步连接。如果给出参数timeout,会允许呼叫者应用于所有TCP数据。如果在timeout规定的时间内还未把数据送到目的地,就关闭连接,一般的默认值是5分钟。
参数precedence或security/compartment是用于规范用户对某一连接的安全性的,如果没有指定则使用默认值。TCP会匹配这两个参数,只有在security/compartment一致而且接收到的precedence小于等于要求的precedence时才会打开连接。当连接的precedence大于要求的值时,从接收到的数据段中取得这一值,并在连接中一直使用这个比较大的值。具体实现时可以给用户权力控制precedence的决定过程。例如,用户可以要求precedence必须安全一致,或在提升precedence时要通知用户。
本地连接名(local connection name)由TCP返回用户,它可以代替<本地套接字,外套接字>标记一个连接。
Send
格式:SEND (local connection name, buffer address, byte count, PUSH flag, URGENT flag [,timeout])
这个命令使指定缓冲区内的数据发向指定连接,如果连接未打开则返回一个错误,一些实现中可能在打开连接以前调用SEND,由SEND自动打开连接。如果设置了PUSH标记,数据必须立刻传送给接收者,而且PUSH位在缓冲区中的最后一个段是必须设置。如果没有设置,此数据段就会因为效率的考虑而和下一个SEND命令传送的数据一起传送。如果设置了URGENT标记,那就必须象上面所述的一样紧急处理。传送方设置的URGENT数目不一定非要等于通知接收方用户的次数。
如果在OPEN中没有指定外套接字,那缓冲区数据会被发送到隐式外套接字。未使用外套接字打开连接的用户仍然可以SEND,而不用知道外套接字地址。但是,如果在指定外套接字前进行SEND,则会出错。用户可以使用STATUES确定连接状态。如果指定了timeout,对于当前连接的当前用户timeout会更改为新的连接。
最简单的实现方法就是在没有把数据发送完毕以前,SEND不把控制权交给发送进程,但是这样可能会造成死锁(例如,双方都试图SEND,而不准备RECEIVE),效率也不好。好的实现方法是在发送一段数据后返回控制权给发送进程,当然如果能够多个SEND同时发送,那更好不过了。有多个SEND需要服务时一般采取先来先服务。
对于本地来说,我们现在假定的是SEND在发送数据后会产生类似中断的东西告诉发送进程数据发送的情况;当然SEND也可以在发送完后立刻告知进行数据发送的情况。我们可以乐观地认为发送是成功的,如果发送失败,连接会因为超时而关闭。在实现中,即使是同步返回情况,也需要一些异步信号,但这些异步信号是用于处理连接的,而不是用于处理数据发送的。既然允许多个SEND同时工作,因此有必要区别返回的信息是哪一个SEND的。具体的情况下面会讨论到。
Receive
格式: RECEIVE (local connection name, buffer address, byte count) > byte count, urgent flag, push flag
此命令分配一个接收缓冲区给指定的连接。如果下面不是一个OPEN命令或者此调用进行未被授权使用此连接返回错误。最简单的实现方法是在缓冲区没有填充完以前不返回控制权,但这样可能会造成严重的死锁。更复杂的实现方法允许同时存在多个RECEIVE,这样会提高效率。这样是在控制复杂的情况下取得了高效率。
如果在PUSH之前的数据已经填满缓冲区,那么对于RECEIVE的响应中就不用设置PUSH位了。缓冲区会容纳尽可能多的数据,如果在缓冲区填充满以前看到PUSH位,将返回缓冲区中的数据并设置PUSH。在处理紧急状态时,如果有URGENT标记,还有紧急数据;如果没有URGENT标记了,就返回所有紧急数据,用户也离开紧急状态。请注意,在紧急指针指向的点以后的那些数据不能和紧急数据一起返回,即使它们在同一个缓冲区内,当然,如果用户指定要这么做例外。
为了区别多个RECEIVE并保证缓冲区不被充满,返回的数据中也要包括缓冲区指针和一个计数器指明现在接收了多少数据。RECEIVE可以有自己专用了缓冲区,也可以和用户共享一个缓冲区。
Close
格式: CLOSE (本地连接名)
此命令关闭连接,如果连接未打开,或未授权可以关闭连接返回错误。在关闭的时候应该注意正常关闭,让所有的发送都发送完数据,也可以如上所说在CLOSE后面加上几个SEND,这就要求用户在收到CLOSE后仍然要进行接收。因此,CLOSE意指“我没有更多的数据要发了”,并不代表“我不再发送任何数据了”。关闭方也可能在超时前不能发出所有数据,这种情况下,要由CLOSE转入ABORT状态。用户可以自己决定在任何时间关闭连接,也可以根据TCP返回的提示关闭。因此关闭操作要和外TCP进行通信,因此在关闭状态可能要呆一会儿,在CLOSE没有返回前调用打开,会返回错误。
Status
格式: STATUS (本地连接名) > status data
这个命令和具体的实现有关,而且有可能会有负作用。返回的信息通常来自有连接相关的TCB。返回的数据块中包括下面的信息:本地套接字,外套接字,本地连接名,接收窗口,发送窗口,连接状态,等待确认的缓冲区数,等待接收的缓冲区数,紧急状态,优先级,security/compartment和传输超时。因此实现不同,所以上述数据项中可能有几项没有意义或根本不存在。如果调用进程没有被授权使用这一连接,返回错误。这一点会防止未被授权的进程获得连接状态。
Abort
格式: ABORT (本地连接名)
此命令中止所有SEND和RECEIVE,删除TCB,将发送特殊的RESERT信息到对方TCP。具体的返回信息会因实现不同而不同。
TCP到用户信息
假定操作系统提供一种可以使TCP异步传送信息到用户程序的机制。当TCP确实通知用户程序时会返回一些特定的信息。通常在这些信息中也会有错误信息,在其它情况下会有关于完成SEND或RECEIVE或其它用户调用的相关信息。会提供下面的几种消息:
本地连接名 都提供
响应串 都提供
缓冲区地址 发送和接收
字节记数 接收
Push标记 接收
Urgent标记 接收

TCP和下层接口
TCP实际上调用下层服务才能在网络上传输数据,在互联网上我们通常认为TCP的下层是IP协议。如果下层是IP层,它提供一些类于服务类型和生存时间的参数。TCP使用这些参数的如下设置:
Type of Service = Precedence: routine, Delay: normal, Throughput: normal, Reliability: normal;或是数字00000000。
Time to Live = 一分钟,或是数字00111100。
请注意:假定的最大数据段的生存时间为2分钟,这里人为指定为1分钟。
如果下层是IP而且使用源地址路由,接口必须允许路由信息的通信。这对建立连接和进行路由是十分重要的。当然也可以不使用IP协议作为TCP的底层协议,但无论下层协议是什么,都必须提供源地址,目的地址和协议域,以及一些决定TCP长度的域,总之一句话,要能够提供类似于IP的功能。
3.9. 事件处理
下面说明的过程是可能的实现,其它实现和本例的过程可能有一点点不同,但只在细节,而决不在结果。TCP的活动可以总结为对事件的响应。事件可以分为三类:用户调用,接收数据段和超时。下面描述的是TCP对具体事件的响应,在许多情况下,相关的动作(响应)要和连接状态相关。
用户调用的有:
OPEN
SEND
RECEIVE
CLOSE
ABORT
STATUS
接收数据段的有:
SEGMENT ARRIVES
超时的有:
USER TIMEOUT
RETRANSMISSION TIMEOUT
TIMEWAIT TIMEOUT
TCP对用户的响应可能是立即的也可能是延时的。错误信息以字符串的形式给出。下面就是一个具体的错误信息:error: connection not open。另外,请记住序列号空间大小为2的32次方。处理数据段的顺序为首先接收,再检查序列号,如果是要接收的就放入接收队列。另外,没有说明状态转移时,TCP保持原来的状态。
OPEN调用
CLOSED状态
创建新的TCB保存连接状态信息,填充本地套接字标记,外套接字,优先级,security/compartment和用户超时信息。注意一部分外套接字在被动OPEN中可能未说明。如果是主动的,而外套接字未指定,返回"error: foreign socket unspecified";如果是主动的,而外套接字指定了,发送一个SYN数据段。选择初始发送序列号ISS。SYN数据段的格式如下<SEQ=ISS><CTL=SYN>,设置SND.UNA为ISS,SND.NXT为ISS+1,进行SYNSENT状态,然后返回。
如果调用者不能访问指定的本地套接字,返回"error: connection illegal for this process"。如果没有空间接收新的连接,返回"error: insufficient resources"。
LISTEN状态
如果处于主动状态,指定了外套接字,可以将连接从被动改为主动,并选择ISS。发送一个SYN数据段,设置SND.UNA为ISS,SND.NXT为ISS+1。进入SYNSENT状态。和SEND一起的数据可以和SYN数据段一起发送,也可以在进入ESTABLISHED状态后发送。如果没有空间接收请求,返回"error: insufficient resources"。如果未指定外套接字,返回"error: foreign socket unspecified"。如果处于以下状态:SYNSENT状态,SYNRECEIVED,ESTABLISHED状态,FINWAIT1状态,FINWAIT2状态,CLOSEWAIT状态,CLOSING状态,LASTACK状态或TIMEWAIT状态时返回"error: connection already exists"。
SEND调用
CLOSED状态
如果用户无权访问连接,返回"error: connection illegal for this process"。否则返回"error: connection does not exist"。
LISTEN状态
如果指定了外套接字,可以将连接从被被动改为主动,选择一个ISS。发送SYN数据段,设置SND.UNA为ISS,SND.NXT为ISS+1。进入SYNSENT状态。和SEND一起的数据可以和SYN数据段一起发送,也可以在进入ESTABLISHED状态后发送。如果没有空间接收请求,返回"error: insufficient resources",如果未指定外套接字,则返回"error: foreign socket unspecified"。
SYNSENT状态和SYNRECEIVED时
在进入ESTABLISHED状态后将需要传送的数据加入队列。如果队列已无空间,则返回"error: insufficient resources"。
ESTABLISHED状态和CLOSEWAIT状态
将缓冲区分段,发送缓冲区数据,并使它带有确认值RCV.NXT。如果没有空间保存缓冲区,则返回"error: insufficient resources"。如果设置了紧急标记,那么SND.UP < SND.NXT1,并设置紧急指针指向发送数据段中的相应位置。
在FINWAIT1,FINWAIT2,CLOSING,LASTACK和TIMEWAIT状态时返回"error: connection closing",不理会请求。
RECEIVE调用
CLOSED状态
如果用户没有权利访问这个连接,返回"error: connection illegal for this process"。如果有权利,则返回"error: connection does not exist"。
在LISTEN,SYNSENT和SYNRECEIVED状态下
在进入ESTABLISHED状态后,将数据放入队列准备处理。如果队列中没有空间,返回"error: insufficient resources"。
在ESTABLISHED,FINWAIT1和FINWAIT2状态下
如果没有接收到足够的数据段满足请求,将请求放入队列。如果队列中没有空间记录RECEIVE,返回"error: insufficient resources"。重新将接收数据段放入接收缓冲区,并返回给用户。在这种情况下,可以设置PUSH标记。如果RCV.UP比现在传送给用户的要大,通知用户有紧急数据。
CLOSEWAIT状态
因为远方TCP已经发送了FIN,RECEIVE必须由现在在缓冲区但还未传送给用户的数据满足。如果没有数据了,RECEIVE会得到"error: connection closing"的响应。
在CLOSING,LASTACK和TIMEWAIT状态下返回"error: connection closing".

CLOSE 调用
CLOSED状态
如果用户没有权利访问这个连接,返回"error: connection illegal for this process"。如果有权利,则返回"error: connection does not exist"。
LISTEN状态
存在着的任何RECEIVE都会返回"error: closing"的响应。删除TCB,然后进入CLOSED状态并返回。
SYNSENT状态
删除TCB并返回"error: closing"响应给任何在队列中的SEND或RECEIVE。
SYNRECEIVED状态
如果没有发送SEND,而且没有等待发送的数据了,则形成并发送FIN数据段,进入FINWAIT1状态;否则在进入ESTABLISHED状态后将命令保存在队列中等待处理。
ESTABLISHED状态
将这一命令保存在队列中,直到所有正在进行的SEND完成后,形成并发送FIN数据段,然后进入FINWAIT1状态。
在FINWAIT1和FINWAIT2状态下
严格地说,这将会是个错误,会收到"error: connection closing"。只要第二个FIN没有发出,也可以收到一个"ok"响应。
CLOSEWAIT状态
直到所有SEND命令完成后再将这个请求放入队列;然后发送FIN数据段,进入CLOSING状态。
在CLOSING,LASTACK和TIMEWAIT状态下返回"error: connection closing"。

ABORT调用
CLOSED状态
如果用户没有权利访问这个连接,返回"error: connection illegal for this process"。如果有权利,则返回"error: connection does not exist"。
LISTEN状态
任何存在的RECEIVE都应该返回"error: connection reset",删除TCB,进入CLOSED状态,然后返回。
SYNSENT状态
对于所有在队列中的SEND和RECEIVE,都返回"connection reset",删除TCB,进入CLOSED状态,然后返回。
在SYNRECEIVED,ESTABLISHED,FINWAIT1,FINWAIT2和CLOSEWAIT状态
发送数据段<SEQ=SND.NXT><CTL=RST>,对于所有在队列中的SEND和RECEIVE,都返回"connection reset",;所有要进行传送或重新传送的数据段立刻进行,删除TCB,进入CLOSED状态,然后返回。
在CLOSING,LASTACK和TIMEWAIT状态下返回"ok",删除TCB,进入CLOSED状态,然后返回。

STATUS 调用
CLOSED状态
如果用户没有权利访问这个连接,返回"error: connection illegal for this process"。如果有权利,则返回"error: connection does not exist"。
LISTEN状态
返回"state = LISTEN"和TCB指针。
SYNSENT状态
返回"state = SYNSEND"和TCB指针。
SYNRECEIVED状态
返回"state = SYNRECEIVED"和TCB指针。
ESTABLISHED状态
返回"state = ESTABLISHED"和TCB指针。
FINWAIT1状态
返回"state = FINWAIT1"和TCB指针。
FINWAIT2状态
返回"state = FINWAIT2"和TCB指针。
CLOSEWAIT状态
返回"state = CLOSEWAIT"和TCB指针。
CLOSING状态
返回"state = CLOSING"和TCB指针。
LASTACK状态
返回"state = LASTACK"和TCB指针。
TIMEWAIT状态
返回"state = TIMEWAIT"和TCB指针。
接收到数据段
如果处于CLOSED状态,所有到达的数据都被抛弃。包括RST的也不例外。如果接收到的数据段不包括RST,则返回一个RST。对于发送TCP要选择它可以认知的确认和序列号。如果关闭ACK位,则序列号为0,格式如下:<SEQ=0><ACK=SEG.SEQ+SEG.LEN><CTL=RST,ACK>如果打开ACK位,格式如下:<SEQ=SEG.ACK><CTL=RST>。
如果处于LISTEN状态,首先检查RST,接收到的RST应该被忽略。下来应该检查ACK,如果连接处于LISTEN状态下,任何ACK都是错误的,应该返回RST段,它的格式如下:<SEQ=SEG.ACK><CTL=RST>。
第三步应该检查SYN,如果SYN位设置了,检查安全性,如果接收数据段中的security/compartment与TCB中的不能匹配,返回RST段,格式如下:<SEQ=SEG.ACK><CTL=RST>。在SEG.PRC大于TCB.PRC的情况下,如果用户和系统允许,则设置TCB.PRC<SEG.PRC,如果用户和系统不允许,发送RST段并返回。其格式如下:<SEQ=SEG.ACK><CTL=RST>。如果SEG.PRC小于TCB.PRC,继续进行。设置RCV.NXT为SEG.SEQ+1,IRS为SEG.SEQ中的值,其它控制信息和数据以后处理。应该选择ISS,并发送SYN段,其格式如下:<SEQ=ISS><ACK=RCV.NXT><CTL=SYN,ACK>。SND.NXT设置为ISS+1,SND.UNA设置为ISS的值,连接状态改为SYNRECEIVED。其它控制信息和数据将在SYNRECEIVED状态中处理,但以于SYN和ACK的处理不应该重复。如果未完全指定LISTEN域,现在就应该指定了。
第四步是处理其它数据和控制信息。其它的数据段(不包括SYN)应该有ACK,因此不要对它进行ACK处理。如果接收到RST段,则它是非法的。如果确实接收到了,抛弃它,直接返回。
如果处于SYNSENT状态。首先检查ACK位,如果设置了ACK位,而且SEG.ACK =< ISS或SEG.ACK > SND.NXT,发送RST。(除非设置了RST位,如果这样,抛弃这个数据段直接返回)。RST段的格式如下:<SEQ=SEG.ACK><CTL=RST>。不用理会收到的数据段,直接返回。如果SND.UNA =< SEG.ACK =< SND.NXT,那么ACK是可以接受的。
下一步检查RST位。在设置了RST的情况下,如果ACK是可以接受的,通知用户"error: connection reset",抛弃接收到的数据段并进入CLOSED状态,删除TCB并返回。如果ACK不能接受,抛弃数据段返回。
第三步检查安全性和优先级。如果security/compartment和TCB中的security/compartment不匹配,发送RST段。在发送RST段的时候,如果已经有ACK了,格式为:<SEQ=SEG.ACK><CTL=RST>,如果没有ACK,格式为<SEQ=0><ACK=SEG.SEQ+SEG.LEN><CTL=RST,ACK>。在没有发现不匹配的时候,如果有ACK,段中的优先级必须和TCB中的匹配,如果不匹配,发送RST,其格式为:<SEQ=SEG.ACK><CTL=RST>;如果未发现不匹配,而且没有ACK的情况下,如果接收到的数据段中的优先级高于TCB中的优先级,在得到用户和系统许可的情况下可以将TCB中的优先级升高,如果用户或系统不许可,提高prec,然后以如下格式发送RST:<SEQ=0><ACK=SEG.SEQ+SEG.LEN><CTL=RST,ACK>,如果接收数据段中的优先级小于TCB中的优先级则继续。在发送了RST后,抛弃数据段并返回。
第四步检查SYN位。只有在ACK位是合法或没有ACK而且数据段中不包括RST的情况下才能进行这一步。如果设置了SYN位,而且security/compartment和优先级合法,那么RCV.NXT设为SEG.SEQ+1,IRS设为SEG.SEQ。SND.UNA应该增加和SEG.ACK相等,在重新发送队列中原来等待确认而现在已经被确认的数据段也被清除。如果SND.UNA > ISS,改变连接状态为ESTABLISHED,形成下面格式的ACK段并发送: <SEQ=SND.NXT><ACK=RCV.NXT><CTL=ACK>。队列中用于发送的数据的控制信息也一起发送,如果段中没有数据或控制信息,则进行第六步,否则返回。如果SND.UNA > ISS不成立,形成SYN,ACK段,格式如下:<SEQ=ISS><ACK=RCV.NXT><CTL=SYN,ACK>,并发送它。如果在段中没有数据或控制信息,待进入ESTABLISHED状态后再进行处理。
第五步,如果SYN或RST位没有设置,抛弃数据段返回。
下来我们来看看其它状态。首先应该检查序列号。在下面状态下
SYNRECEIVED状态
ESTABLISHED状态
FINWAIT1状态
FINWAIT2状态
CLOSEWAIT状态
CLOSING状态
LASTACK状态
TIMEWAIT状态
段按顺序处理,首先抛弃重复的段,对于以后的处理要根据SEG.SEQ的大小进行。如果有的段内的新老内容重叠在一起,那只用处理新的那一部分。下面是对接收到的数据的可接受性测试中的四种情况:
段长度接收窗口测试
00SEG.SEQ = RCV.NXT
0>0RCV.NXT =< SEG.SEQ < RCV.NXT+RCV.WND
>00不接受
>0>0RCV.NXT =< SEG.SEQ < RCV.NXT+RCV.WND或RCV.NXT =< SEG.SEQ+SEG.LEN1 < RCV.NXT+RCV.WND
如果RCV.WND = 0,除了合法的ACK,URG和RST段外拒绝其它的数据段。如果接收到的数据段不可接受,应该返回一个应答,格式如下:<SEQ=SND.NXT><ACK=RCV.NXT><CTL=ACK>。在发送完应答后,抛弃不可接受的数据段,然后返回。
第二步检查RST位。
如果处于SYNRECEIVED 状态时,而且处于设置了RST的情况下,如果连接以被动OPEN开始,将连接返回到LISTEN状态,不需要通知用户;如果连接以主动OPEN打开,拒绝连接,并通知用户"connection refused"。在上面任何一种情况下,所有在重发队列中的数据都要删除。在主动OPEN的那种情况下,进入CLOSED状态,删除TCB然后返回。
如果处于ESTABLISHED,FINWAIT1,FINWAIT2或CLOSEWAIT状态时,而且RST已经设置,那么任何存在的RECEIVE和SEND都会收到"reset"。所有队列中的数据段都应该立即发送。用户也会收到"connection reset"。进入CLOSED状态,删除TCB并返回。
如果处于CLOSING状态,LASTACK状态或TIMEWAIT状态,而且RST已经设置,进入CLOSED状态,删除TCB并返回。
检查安全和优先级
在SYNRECEIVED状态下
如果段中的security/compartment和优先级和TCB中的不匹配,发送RST并返回。
在ESTABLISHED状态下
如果段中的security/compartment和优先级和TCB中的不匹配,发送RST ,所有存在的RECEIVE和SEND接收到"reset",立即发送所有队列中的数据段,用户接收到"connection reset"。进入CLOSED状态,删除TCB并返回。
第四步检查SYN位,如果连接处于以下状态
SYNRECEIVED
ESTABLISHED状态
FINWAIT STATE1
FINWAIT STATE2
CLOSEWAIT状态
CLOSING状态
LASTACK状态
TIMEWAIT状态
如果SYN在窗口中就是错误,发送RST,任何存在的RECEIVE和SEND收到"reset",所有在队列中的数据段立即发送,用户也接收到"connection reset",进入CLOSED状态,删除TCB并返回。如果SYN未在窗口中,这一步不会发生。
第五步检查ACK域
如果ACK位关闭,抛弃数据段返回。如果ACK域打开的情况下,如果连接处于
SYNRECEIVED状态时
如果SND.UNA =< SEG.ACK =< SND.NXT,进入ESTABLISHED状态。如果段的确认消息不可接受,形成如下形式的RST并发送:
<SEQ=SEG.ACK><CTL=RST>
ESTABLISHED状态时
如果SND.UNA < SEG.ACK =< SND.NXT,设置SND.UNA < SEG.ACK。因此而对重新传送队列中数据段的确认也带来了对这些数据段的删除。用户应该接收对缓冲区的主动确认,如果ACK是重复的(SEG.ACK < SND.UNA)可以忽略这个ACK。如果ACK确认了还未发送的东西(SEG.ACK > SND.NXT),那么可以发送ACK,抛弃数据段并返回。
如果SND.UNA < SEG.ACK =< SND.NXT,应该更新发送窗口。如果(SND.WL1 < SEG.SEQ)或(SND.WL1 = SEG.SEQ且SND.WL2 =< SEG.ACK),设置SND.WND < SEG.WND,SND.WL1 < SEG.SEQ和SND.WL2 < SEG.ACK。
FINWAIT1状态
除了对于ESTABLISHED状态的处理外,如果确定了FIN,则进入FINWAIT2状态并在这个状态下继续处理。
FINWAIT2状态时
除了对于ESTABLISHED状态的处理外,如果重新发送队列为空,确认用户的CLOSE,但不删除TCB。
CLOSEWAIT状态时
同ESTABLISHED状态的处理。
CLOSING状态时
除了对于ESTABLISHED状态的处理外,如果确定了FIN,则进入TIMEWAIT状态,如果未确认,则忽略这个段。
LASTACK状态时
在此状态下唯一可能发生的就是重要发送远程FIN。如果确认了FIN,则删除TCB,进入CLOSED状态并返回。
TIMEWAIT状态时
在此状态下唯一可能发生的就是重要发送远程FIN。确认它,并重新开始2 MSL超时。
第六步检查URG位,如果连接处于ESTABLISHED状态,FINWAIT1状态或FINWAIT2 状态,而且URG位被设置,那么RCV.UP < max(RCV.UP,SEG.UP),通知用户远方有紧急数据,如果用户已经处于紧急状态,不用再多嘴了。连接在此时不会处于CLOSEWAIT状态,CLOSING状态,LASTACK状态或TIMEWAIT状态,因为还没有从远方获得FIN。
第七步处理段数据
处于ESTABLISHED状态,FINWAIT1 状态或FINWAIT2 状态时,在进入ESTABLISHED状态后才可能向用户接收缓冲区传送数据。段中的数据可以移向缓冲区,直到缓冲区满或段为空为止。如果段为空并带有标记PUSH,在返回缓冲区数据后要通知用户接收到PUSH。TCP传送数据时必须对接收到的数据也发给确认。前面已经说过对RCV.NXT和RCV.WND的处理,这里不再多说了。发送的确认有如下格式:<SEQ=SND.NXT><ACK=RCV.NXT><CTL=ACK>。
而CLOSEWAIT状态,CLOSING状态,LASTACK状态或TIMEWAIT 状态根本不会发生,因为还未从远程TCP接收到FIN。
第八步检查FIN位。如果状态是CLOSED,LISTEN或SYNSENT,不要处理FIN,因为此时的SEG.SEQ不会的意义,应该直接抛弃数据段返回。如果设置了FIN位,通知用户"connection closing"中止所有正在进行的RECEIVE,增加RCV.NXT超过FIN,对FIN发送确认。
如果此时处于:SYNRECEIVED状态或ESTABLISHED状态进入CLOSEWAIT状态。
如果此时处于FINWAIT1 状态
如果确定了FIN段,那么进入TIMEWAIT状态,打开timewait计数器,关闭其它计数器,如果没有确认,进入CLOSING状态。
如果此时处于FINWAIT2状态
进入TIMEWAIT状态,关闭其它计数器,打开timewait计数器。
如果此时处于CLOSEWAIT状态或CLOSING状态或LASTACK状态,保留各自原来的状态。
如果此时处于TIMEWAIT状态,保持在TIMEWAIT状态。重新开始2 MSL timewait超时。

用户超时
对于任何一种状态,用户超时的情况下,发送队列中的数据,返回"error: connection aborted due to user timeout",删除TCB,进行CLOSED状态并返回。

重发超时
在任何状态下,如果重发队列中的数据段发送超时,将它再次放到队列首部重新发送。
TIMEWAIT超时
如果timewait超时,删除TCB,进行CLOSE状态并返回。
四.结束语
本文介绍了作为一个面向连接的传输层TCP传输控制协议,从它的含义与其在网络上地位说明它的重要性,着重分析它是如何在其网络环境下的具体工作过程。其中有很多专业术语,难免有理解的难度。我是想起老师曾说过的那句话:只要了解30%也要完成论文,我才能勉强写完,说真的这篇论文我了解的还不到20%,尤其是它是如何工作的,请老师谅解。

三 : 传输服务的分类及传输层协议类型

一、传输层传输服务的分类

A型:网络连接具有可接受的低差错率和可接受的低故障通知率。[www.61k.com]
该类服务是一个完整的、理想的、可靠的服务。
该类服务下,网络中传输的分组不会丢失和失序,因此传输层不需要提供故障恢复和重新排序服务。

B型:网络连接具有可接受的低差错率和不可接受的高故障通知率。

该类网络服务是完美的分组递交,但存在网络连接释放和网络连接重建问题。

C型:具有不可接受的高差错率。

网络连接不可靠,可能会丢失分组或出现重复分组;
存在网络连接释放问题。

二、传输层协议类型

0类协议
面向A型网络服务,其功能只是建立一个简单的端到端的传输连接,在数据传输阶段具有将长数据报文分段传输的功能。

没有差错恢复和将多条传输连接复用到一条网络连接上的功能。

1类协议
提供基本的传输连接,面向B型网络服务
功能:在0类协议的基础上增加了基本差错恢复功能。

**基本差错:出现网络连接断开或网络连接失败,或者收到了未被认可的传输连接的数据单元。
2类协议

具有在一个网络连接上复用多个传输连接的能力,也面向A型网络服务。

具有流量控制功能而没有网络连接故障恢复功能。

3类协议

面向B型网络服务
具有差错恢复功能
具有复用功能。

4类协议
面向C型网络服务;
具有差错检测、差错恢复、复用等功能;
可以在网络服务质量差时保证高可靠的数据传输;
最复杂、最全面

四 : 网络协议概述:物理层、连接层、网络层、传输层、应用层详解

信号的传输总要符合一定的协议(protocol)。比如说长城上放狼烟,是因为人们已经预先设定好狼烟这个物理信号代表了“敌人入侵”这一抽象信号。这样一个“狼烟=敌人入侵”就是一个简单的协议。协议可以更复杂,比如摩尔斯码(Morse Code),使用短信号和长信号的组合,来代表不同的英文字母。比如SOS(***---***,  *代表短信号,-代表长信号)。这样"***= S, ---=O"就是摩尔斯码规定的协议。然而更进一层,人们会知道SOS是求助信息,原因是我们有“SOS=求救”这个协议存在在脑海里。所以"***---***=SOS=求救"是一个由两个协议组成的分层通信系统。

使用Morse Code的电报机

计算机之间的通信也要遵循不同层次的协议,来实现计算机的通信。

物理层(physical layer)

所谓的物理层,是指光纤、电缆或者电磁波等真实存在的物理媒介。这些媒介可以传送物理信号,比如亮度、电压或者振幅。对于数字应用来说,我们只需要两种物理信号来分别表示0和1,比如用高电压表示1,低电压表示0,就构成了简单的物理层协议。针对某种媒介,电脑可以有相应的接口,用来接收物理信号,并解读成为0/1序列

连接层(link layer)

在连接层,信息以帧(frame)为单位传输。所谓的帧,是一段有限的0/1序列。连接层协议的功能就是识别0/1序列中所包含的帧。比如说,根据一定的0/1组合识别出帧的起始和结束。在帧中,有收信地址(Source, SRC)和送信地址(Destination, DST),还有能够探测错误的校验序列(Frame Check Sequence)。当然,帧中最重要的最重要是所要传输的数据 (payload)。这些数据往往符合更高层协议,供网络的上层使用。与数据相配套,帧中也有数据的类型(Type)信息。连接层协议不关心数据中到底包含什么。帧就像是一个信封,把数据包裹起来。

以太网(Ethernet)和WiFi是现在最常见的连接层协议。通过连接层协议,我们可以建立局域的以太网或者WiFi局域网,并让位于同一局域网络中的两台计算机通信。连接层就像是一个社区的邮差,他认识社区中的每一户人。社区中的每个人都可以将一封信(帧)交给他,让他送给同一社区的另一户人家。

连接层:社区小邮差

 

网络层(network layer)

不同的社区之间该如何通信呢? 换句话说,如何让WiFi上的一台计算机和以太网上的另一台计算机通信呢?我们需要一个“中间人”。这个“中间人”必须有以下功能: 1. 能从物理层上在两个网络的接收和发送0/1序列,2. 能同时理解两种网络的帧格式。路由器(router)就是为此而产生的“翻译”。一个路由器有多个网卡(NIC,Network Interface Controller),每个NIC可以接入多个网络,并理解相应的连接层协议。在帧经过路由到达另一个网络的时候,路由会读取帧的信息,并改写以发送到另一个网络。所以路由器就像是在两个社区都有分支的邮局。一个社区的邮差将信送到本社区的邮局分支,而邮局会通过自己在另一个地区的分支将信转交给另一个社区的邮差手中,并由另一个社区的邮差最终送到目的地。

通过路由连接的WiFi和以太网

整个通信过程如下:

WiFi上的计算机1 -> 路由WiFi接口 ->  路由以太网接口 -> 以太网上的计算机2

(蓝色表示WiFi网络,绿色表示以太网络)

在连接层,我们的一个帧中只能记录SRC和DST两个地址。而上面的过程需要经过四个地址 (计算机1,WiFi接口,以太网接口,计算机2)。显然,仅仅靠连接层协议无法满足我们的需要。由于连接层协议开发在先,我们无法改动连接层协议,只能在连接层的数据(payload),也就是信纸内部下功夫了。IP协议应运而生。

计算机1,路由器和计算机2都要懂得IP协议。当计算机1写信的时候,会在信纸的开头写上这封信的出发地址和最终到达地址 (而不是在信封上),而在信封上写上要送往邮局。WiFi网的邮差将信送往邮局。在邮局,信被打开,邮局工作人员看到最终地址,于是将信包装在一个新的信封中,写上出发地为邮局,到达地为计算机2,并交给以太网的邮差,由以太网的邮差送往计算机2。

(IP协议还要求写如诸如校验等信息,交通状况等信息,以保护通信的稳定性。)

转交给邮局

 

在连接层,邮差只负责在本社区送信,所以信封上的地址总是“第一条街第三座房子”或者说“中心十字路口拐角的小房子”这样一些本地人才了解的地址描述,这给邮局的工作带来不便。所以邮局要求,信纸上写的地址必须是一个符合官方规定的“邮编”,也就是IP地址。这个地址为世界上的每一个房子编号(邮编)。当信件送到邮局的时候,邮局根据邮编,就能查到对应的地址描述,从而能顺利改写信封上的信息。

每个邮局一般连接多个社区,而一个社区也可以有多个邮局,分别通往不同的社区。有时候一封信要通过多个邮局转交,才能最终到达目的地,这个过程叫做route。邮局将分离的局域网络连接成了internet,并最终构成了覆盖全球的互联网。

传输层(transport layer)

上面的三层协议让不同的计算机之间可以通信。但计算机中实际上有许多个进程,每个进程都可能有通信的需求。这就好像一所房子里住了好几个人(进程),如何让信精确的送到某个人手里呢?遵照之前相同的逻辑,我们需要在信纸上写上新的信息,比如收信人的姓名,才可能让信送到。所以,传输层就是在信纸的空白上写上新的“收信人”信息。每一所房子会配备一个管理员(传输层协议)。管理员从邮差手中接过信,会根据“收信人”,将信送给房子中的某个人。

管理员

传输层协议,比如TCP和UDP,使用端口号(port number)来识别收信人(某个进程)。在写信的时候,我们写上目的地的端口。当信到达目的地的管理员手中,他会根据传输层协议,识别端口号,将信送给不同的人。

TCP和UDP协议是两种不同的传输层协议。UDP协议类似于我们的信件交流过程。TCP协议则好像两个情人间的频繁通信。一个小情人要表达的感情太多,以致于连续写了好几封信。而另一方必须将这些信按顺序排列起来,才能看明白全部的意思。TCP协议还有控制网络交通等功能。

应用层(application layer)

通过上面的几层协议,我们已经可以在任意两个人(进程)之间进行通信。然而每个人实际上从事的是不同的行业。有的人是律师,有的人外交官。比如说律师之间的通信,会用严格的律师术语,以免产生纠纷。再比如外交官之间的通信,必须符合一定的外交格式,以免发生外交误会。再比如间谍通过暗号来传递加密信息。应用层协议是对信件内容进一步的用语规范。应用层的协议包括用于Web浏览的HTTP协议,用于传输文件的FTP协议,用于Email的IMAP等等。

 外交通信

总结

总过网络分层,我们从原始的0/1序列抽象出

本地地址(邮差)、邮编(邮局)、收信人(管理员)、收信人行业(用语规范)

这些概念。这些概念最终允许互联网上的分布于两台计算机的两个进程相互通信。

写信人必须按照各层的协议,封装好整个信封 (encapsulation);而收信人则按照相反的顺序,来拆开这个信封。整个过程是可读信息 -> 二进制 -> 可读信息。计算机只能理解和传输0/1序列,而计算机的用户则总是输入和输出可读信息。网络协议保证了可读信息在整个转换和传输过程中的完整性。

计算机协议本身还有更多的细节需要深入。这篇文章只是从分层的角度描述各个层次所实现的功能。 

本文标题:传输层协议-Internet 传输层协议
本文地址: http://www.61k.com/1138919.html

61阅读| 精彩专题| 最新文章| 热门文章| 苏ICP备13036349号-1