第一章.概述

Internet的成功

Internet体系结构被设计成支持现有网络互联,同时提供了广泛的服务与协议操作。
选用数据包的分组交换主要是因为它的鲁棒性与效率,而相对来说数据安全性与交付可预测性(例如有限的延迟)是次要因素。

分层设计

OSI模型:7层
TCP/IP:4层(若分层为5层则加上一个物理层)
TCP/IP协议族的三个主要层次是网络层、传输层与应用层

差错控制与流量控制

总体来说,Internet协议中采取“尽力而为交付”。网络不会花费巨大努力确保数据在没有差错或缺陷的情况下交付,差错通常由校验码来检出,但检出后出错的数据报也仅仅被丢弃而无进一步行动。
同样流控机制也是如此,流控机制将保证发送方不会以比接收方最大接受能力还快的速度发送,若发送超速,发送方将会被通知降速。

网络层与传输层

网络层(IP)提供了一个不可靠的数据报服务,必须由Internet中所有可寻址的系统来实现。
而传输层(TCP与UDP)为端主机上运行的应用程序提供了端到端服务:
其中TCP提供了带有流量控制与拥塞控制的有序、可靠的流交付
UDP除了用于多路分解的端口号和错误检测机制外,基本功能没有超越IP

DNS

DNS是一个运行在Internet上的分布式数据库应用程序,它提供主机名与IP地址的相互转换。

第二章.Internet地址结构

IP地址的表示

IPv4地址为32位,用点分十进制表示,例如165.195.130.107

IPv6地址为128位,用被冒号分隔开的8组4个十六进制数表示,例如5f05:2000:80ad:5800:0058:0800:2023:1d71
通常来说一个块中的前导的0可以省略,全0的块可以用::代替,但::只能出现一次并且应在能替代的最长处。

分类寻址

IPv4地址空间被分为5大类

子网寻址

由于A类与B类为一个网段分配了太多的主机号,而实际我们希望在一个站点接入Internet后为其分配一个网络号,然后由站点管理员进一步划分本地的子网数。

如上例,前16位网络号由Internet集中分配,而后16位由站点本地管理,将其划分为8位的子网号与8位的主机号。
而在此过程中,有多少位用于网络号与子网号的实现方法是使用子网掩码

子网掩码与IP地址按位与操作后,就能得到对应的网络号与子网号
这里值得注意的是:站点之外的路由器做出的路由决策指基于地址的网络号部分,并不需要子网部分,因此子网掩码是纯粹的站点内部的局部问题。

广播地址

在每个IPv4子网中,有一个特殊地址被保留用作子网广播地址。
该地址网络号与子网号被设置为合适的值,而主机号各位则被全部设置成1。
更特殊的是:特殊用途地址255.255.255.255被保留用作本地网络广播(不会被路由器转发)。
实现方法是:将子网掩码取非,再与IPv4地址进行或运算。

CIDR和聚合

CIDR 被称为无类别域间路由
为缓解IPv4地址耗尽的压力,一个短期解决方案是使用CIDR
CIDR 对原来用于分配A类、B类和C类地址的有类别路由选择进程进行了重新构建。
它用 13-27位长的前缀取代了原来地址结构对地址网络部分的限制(3类地址的网络部分分别被限制为8位、16位和24位)
CIDR需要提供一个CIDR掩码:
以CIDR地址222.80.18.18/25为例,其中“/25”表示其前面地址中的前25位代表网络部分,其余位代表主机部分。
上述技术成功缓解了IPv4地址的压力,但未解决路由表条目的爆炸性增长(将显著影响路由性能)
最终发现将网络拓扑排列成一棵树,并对其使用CIDR技术分配地址可以获得一个较小的路由表,由于路由分层,某个路由器不需要知道同层兄弟结点的子节点,只需将多个子节点聚合成一个CIDR掩码更短的网络地址块(可以覆盖更多地址空间)。

IPV6单播地址

IPv6单播地址与IPv4有所不同,最重要的是:无论是单播地址还是组播地址,都需要明确指出地址的有效范围。典型性的范围包括节点本地、链路本地和全球范围。

第三章.链路层

CSMA/CD

当多个站共享同一网络,CSMA/CD 作为一种分布式算法可以控制每一个站发送自己的数据。
一个站首先检测目前网络上正在发送的信号,并在网络空闲时发送自己的帧。如果碰巧其他站同时发送,发生重叠的电信号被检测为一次碰撞,这种情况下,每个站等待一个随机时间,然后再次尝试发送,等待时间采用二进制指数退避的方式(随后每次再碰撞等待时间加倍,在尝试16次后超时)

以太网帧格式

Ethernet II 帧格式
D.MAC为目的MAC地址,S.MAC为源MAC 地址
Type字段中,常见值为:IPv4(0x0800),IPv6(0x86DD),ARP(0x0806)
FCS为32位的CRC校验码

IEEE 802.3 帧格式

以太网帧有最小和最大尺寸,最小的帧为64字节,要求数据区长度最小为46字节,若不足则填充字节(补0)到数据区尾部。
这个最小尺寸的帧的发送时间与帧的往返时间大致相同(略大于),保证发送过程中如果发生冲突,能在碰撞信号返回后停止发送(否则冲突信号还未传回,该帧已发送完毕)。
传统以太网的最大帧长度是1518字节。最大帧长度如果太大,整个帧出错的概率也会升高,同时重传的代价也会变大;但如果最大帧长度太小,则该帧的利用率(有效载荷与帧长的比)又太小。

802.1p/q:虚拟局域网与Qos标签

802.1q中定义了虚拟局域网(VLAN)的功能,该功能保证了物理分组与逻辑拓扑分组的分离。连在同一台交换机但在不同VLAN分组中的主机,在逻辑上看像是在不同网段那样;而连在不同交换机上但在同一个VLAN分组中的主机组成一个广播域,若有组内广播则只在同一VLAN分组内广播。
帧中保留了一个称为VLAN标签的标记,其中包含12位VLAN标识符(提供4096-2个VLAN,保留0与4095)

其中802.1p中还包含支持QoS的3位的优先级,该字段用于表示QoS级别:0级为最低优先级,用于传统的尽力而为的流量;7级为最高级,可用于关键路由或网管功能

网桥和交换机

交换机本质上是高性能的网桥,用于连接多个物理的链路层网络。
每个网桥内部有一个表,它采用后向学习算法来探知网络的拓扑结构,并决定通过目的MAC地址将消息转发给哪一个端口,若表项不存在,则使用泛洪算法探知。

生成树协议

问题出现在:当网络拓扑中出现环路时,帧的泛洪可能导致死循环的泛洪灾难。
解决方案是:使用生成树协议(STP),确保任意两个节点之间只有一条路径,使拓扑结构中最终不含环路。
值得注意的是,这是一个动态协议,定期使用生成树算法,将可以适应网络拓扑结构的变化。
具体实现时,是通过交换一种称为“网桥协议数据单元”(BPDU)的帧来实现的。
STP的第一个工作是选取根网桥,根网桥是在网络(或VLAN)中标识符最小的网桥。当一个网桥初始化时,它假设自己是根网桥,并用自己的网桥ID发送配置BPDU消息,如果它检测到一个ID更小的网桥,就停止发送自己的帧,并基于接收到的ID更小的帧构造下一步发送的BPDU。
而当一个端口进入阻塞或转发状态时,意味着发生了拓扑变化。当网桥检测到一个拓扑变化,它将向根端口之外的端口发送拓扑变化通知。树中通向根的下一网桥将消息转发直至根网桥收到通知。
根网桥会在后续的周期性配置消息中设置TC位,这些消息将被转发并被阻塞的网桥接收,减少其延时计时器的有效期,这样错误条目可得到快速清除和重新学习。

无线局域网-802.11(WiFi)

802.11使用RTS/CTS交换来避免隐藏终端问题(不再详述),但由于隐藏终端问题很少发生,可将RTS阈值设置为很大(1500+)来禁用该功能,可避免该交换带来的额外开销。
802.11的介质访问控制DCF(分布式协调功能):
DCF是一种CSMA/CA方法,这个行为类似于CSMA/CD,但802.11的载波侦听能以物理和虚拟方式实现。

虚拟侦听

在每个站本地都维持一个网络分配向量(NAV),它被用于估计介质传输当前帧所需要的时间,以及下一次传输需要等待的时间。当一个站侦听到一个持续时间大于自己的NAV时,它将自己的NAV更新为这个值。而由于RTS与CTS帧中都有一个持续时间字段,因此在使用NAV之后,在其覆盖范围内的任何站都能看到该字段,以决定自己应该什么时候开始下一次探测以便传输。

物理载波侦听(CCA)

它基于能量和波形识别,用于了解介质当前是否处于繁忙状态,通常与NAV结合使用,以确定一个站在传输之前是否需要等待。

点到点协议(PPP)

PPP支持建立链接的基本方法-链路控制协议(LCP),由于LCP只用于在点到点链路上建立和维护低层的双方通信路径,因此PPP只需关心一条链路的两端,而不必关心共享资源访问的问题。
帧格式如下:
其中7E为其帧标志,使用字节填充法,但在同步线路上使用比特填充法。
转义符为7D,数据部分的7E将被写为0X7D5E,还原时删去所有的7D,并将其后面的一个字节与0X20相或,就可得到原本的帧。

环回

有时用户希望使用Internet协议与本机上的服务器通信,为实现这种功能,通常使用一个虚拟的环回网络接口来实现,以127开始的IPv4地址就是为该目的而保留的,为此保留的IPv6地址为 ::1,为其分配的名称叫做localhost

MTU与路径MTU

在很多链路层网络中,携带高层PDU的帧大小是有限制的。以太网有效载荷的字节数通常被限制为1500,PPP通常采用相同大小以与以太网兼容。
链路层的这种性质被称为MTU(最大传输单元),如果IP需要发送一个数据报,并且长度大于该值,就要通过分片多次传输。
当两台主机跨越多个网络进行通信时,每条链路可能有不同的MTU,在包含所有链路的整个网络路径上,最小的MTU称为路径MTU。
路径通常不对称,路径MTU不需要在两个方向上相同。

隧道基础

某些情况下,两台计算机通过Internet或其它网络建立一条虚拟链路,虚拟专用网络(VPN)专门用于提供这种服务。其中实现这种服务最常用的方法称为隧道。
隧道一般是在高层(或同层)分组中携带低层数据。
用于建立隧道的3个常见协议:
通用路由封装协议(GRE)
Microsoft专用的点到点隧道协议(PPTP)
第2层隧道协议(L2TP)

第四章.地址解析协议

ARP的目的

IP协议的设计目标是为跨越不同类型物理网络的分组交换提供互操作,网络硬件接口通常有一个主要的硬件地址(例如以太网或802.11无线接口的48位地址),这需要网络层软件使用的地址和底层网络硬件使用的地址之间进行转换。
地址解析协议 就是用来解决从网络层地址到相关硬件地址的动态映射问题。
事实上,ARP协议几乎总是用于32位IPv4地址到以太网48位MAC地址的映射。
这里值得注意的是:ARP协议仅用于IPv4,IPv6使用了邻居发现协议,并已被合并入了ICMPv6。

ARP的本地性

ARP仅提供位于同一IP子网内的IP地址-MAC地址映射。因此收到一个请求后,它首先判断该服务位于本地(同一IP子网的一部分)还是远程。如果是远程的,需要一台可到达目的地的路由器。仅在到达位于同一IP子网的系统时,ARP才能工作。

ARP的工作流程

(1)当数据报到达与目的IP地址的同一子网内时,此时需要提供从IP地址到MAC地址的映射,ARP开始工作。
ARP工作在正常模式下,只适用于广播网络(ARP运行的前提是链路层能将一个消息交付到它所连接的所有网络设备)
(2)在共享的链路层网段上,ARP向所有主机发送一个称为 ARP请求 的以太网帧,这被称为链路层广播。
(3)同一广播域中的所有系统都将受到该请求,接着如果某个系统配置的IP地址是ARP请求中的地址,则它响应一个 ARP应答 ,这个应答包含IPv4地址和对应的MAC地址。(重点是 这个应答通常不是广播,而是直接发送给请求的发送方 )同时,接受ARP请求的主机学习IPv4到MAC地址的映射,并记录在内存中以备下次使用。
(4)当ARP应答被原始请求的发送方接收,它已经得知了目的IP地址对应的MAC地址,此时可以发送该数据报。发送方通常将该数据报封装在以太网帧中直接发送到目的主机,并使用由ARP交换学习到的以太网地址作为目的地址(仅指向目的主机,其他主机不会收到),这个过程称为 直接交付

ARP缓存

保证ARP高效运行的关键是维护每个主机和路由器上的ARP缓存,该缓存使用地址解析为每个接口维护从网络层地址到硬件地址的最新映射。某个条目的生存期一般在20分钟。
Linux或Windows中都可使用arp命令查看ARP缓存,选项-a用于显示所有条目。

ARP帧格式

其中Op字段用于标识帧类型,其中ARP请求(1),ARP应答(2),RARP请求(3),RARP应答(4)

这里附上用Wireshark抓到的包

免费ARP

ARP的另一功能被称为免费ARP,他发生在一台主机发送ARP请求以寻找自己的地址时,通常出现在启动时。
目的一是为了确认另一台主机是否配置了相同的IP地址,发送免费ARP的主机并不期望得到回应,但若收到了回应,说明同一广播域内出现了相同的IP地址,表明一个系统配置错误。
目的二是为了在主机改变了硬件地址时,通知其他主机。当一台主机接收到一个免费ARP请求,并且该请求来自一个已存在缓存中的IPv4地址,则缓存条目会更新为发送方的新MAC地址。

Internet协议

IP协议的简单特性

IP提供了一种尽力而为、无连接的数据报交付服务。
“尽力而为”意味着不保证数据报能成功到达目的地。虽然IP不是简单丢弃所有不必要流量,但它也不对自己尝试交付的数据报提供保证,可靠性必须由上层提供。

IPv4数据报格式

头部长度为20字节
第一个字段为版本号,IPv4为4,IPv6为6
首部长度字段为4位,表示头部长度/4,正常值为5
DSCP为6位,称为区分服务字段。
ECN为2位,用来表示显式拥塞通知。
总长度字段表示IPv4数据报的总长度。
标识字段为了将分片后属于不同数据报的片段区分开。
DF表示是否允许分片。
MF表示该片后是否还有属于该数据报的更多片。
片段偏移字段表示该片位于整个数据报的第几个字节/8。
TTL表示生存期,该字段达到0时,数据报被丢弃。
协议字段包含一个数字,表示数据报有效载荷部分的数据类型。UDP(17),TCP(6)。
首部校验和仅计算IPv4头部,采用的是Internet校验和(16位反码和的反码,验证时,消息加校验和应为全1),而非CRC校验。
IP提供了一些可供数据报选的选项,若要了解详见【RFC0791】

IPv6数据报格式

头部长度为40字节

IPv6扩展头部

IPv6中,那些由IPv4选项提供的特殊功能,通过在IPv6头部之后增加扩展头部实现(常见IPv4路由和时间戳功能)。
扩展头部和更高层协议(如TCP与UDP)头部与IPv6头部连接起来构成级联的头部。每个头部“下一个头部”字段表示紧跟着的下一头部的类型。
其中IPv6的分片就是以分片头部的形式控制。

IP转发

路由器中的转发表用来控制接收到一个数据报后,应当如何进行转发工作。
转发表中的每个条目应当包含:
目的地、掩码、下一跳、接口
根据路由表能够完成路由转发工作的有多种路由协议:包括RIP,OSPF,BGP,IS-IS。
其中RIP与OSPF属于内部网关协议。
RIP使用距离矢量算法(每个站向邻居报告自己到其他所有节点的最短路径并更新),实现方法:某站发出请求,其他所有站响应它,据此更新路由表。
OSPF使用链路状态路由协议(每个站向全体报告自己到邻居的最短路径并用迪杰斯特拉算法寻路),实现方法:向邻居泛洪。
BGP是边界网关协议,是自治系统之间的路由选择协议。

DHCP和自动配置

功能

DHCP是一种流行的客户机/服务器协议,用于为主机指定配置信息。相关设备通常使用DHCP获得IP地址、子网掩码、路由器的IP地址、DNS服务器的IP地址。

报文格式

配置过程


客户机首先广播一个discover消息。
服务器会响应一个offer消息,并把“yiaddr”字段提供分配的IP地址,包括租用时间等信息。
当接收到一台或多台服务器的offer消息后,客户机确定自己想接受哪个offer,并广播一个包含“服务器标识”选项的request消息。
多台服务器会收到request消息,但只有request消息中标识的服务器同意绑定,而其他服务器清除与该请求相关的状态。完成绑定后,服务器会返回一个ACK,通知客户机现在可以使用该地址(若无法分配将会返回NAK)。
若一台客户机在租约到期前放弃该地址,它将发送一个release消息。
这里省略了DHCPv6的部分

DHCP中继

最简单的网络中,一个DHCP服务器可供同一局域网中的客户机使用。但在更复杂的网络中,可通过一个或更多DHCP中继代理来中继DHCP流量,这可以将DHCP操作扩展到跨越多个网段。

以太网上的PPP

对于大多数局域网和一些广域网,DHCP提供了最常用的客户机系统配置方法。对于广域网(例如DSL )常用另一种基于PPP的方法替代它。
这种方法涉及在以太网中携带PPP,因此称为以太网上的PPP(PPPoE)。
在这里不详述配置过程,仅知道DHCP也不是适用于所有主机配置即可,且PPPoE的方式是P2P(对等式)的

防火墙和网络地址转换

防火墙

确保终端系统免受攻击的焦点在于如何利用防火墙过滤部分流量以限制流量流向终端系统。
最常用的两种防火墙是:代理防火墙和包过滤防火墙
包过滤防火墙是一个互联网路由器,能够丢弃符合(或不符合)特定条件的数据包。
而代理防火墙是一个多宿主的服务器主机,也就是说,它是TCP和UDP传输关联的终点,通常不会在IP协议层中路由IP数据报。
其中,代理防火墙的两种最常见形式是HTTP代理防火墙和SOCKS防火墙。
前者也称Web代理,只能用于HTTP与HTTPS协议。这些代理对于内网用户来说像是Web服务器,对于被访问的外部网站来说就像是Web客户端,这种Web代理往往提供Web缓存功能,这些缓存保存网页的副本,便于后续访问时可以从缓存中直接获取,而不再需要原始的Web服务器。
SOCKS协议比HTTP代理访问使用更加广泛,可用于除Web以外的其他服务。配置完成后,可进行选择性的DNS查找。

网络地址转换

NAT本质上是一种允许在互联网的不同地方重复使用相同的IP地址集的机制。NAT原本是为解决IPv4地址即将耗尽的问题,NAT的使用大大延缓了IPv6的推进进程。
大多数的NAT同时执行转换和包过滤两项工作。
NAT包括基本NAT(basic NAT)和网络地址端口转换(NAPT)。
基本上NAT只执行IP地址的重写,本质上是将一个私有地址改写成一个公共地址,但这种类型的NAT不是最流行的,因为它无助于减少需要使用的IP地址数量。
而NAPT使用传输层标识符(TCP/UDP端口和ICMP查询标识符)来确定一个特定的数据包到底和NAT内部的哪台私有主机关联。这使得大量主机可以共用一个公有地址。
在NAT后面使用的私有地址范围不受除了本地网络管理人员以外任何人的限制,因此有可能在私有范围内采用全局地址空间,而相同地址的本地系统会屏蔽掉远端系统。
NAT提供了一定程度上的类似防火墙的安全性。默认情况下,从互联网无法访问NAT私有端的所有系统。

ICMP协议

ICMP协议提供了方式让用户发现那些发往目的地址失败的IP数据包,它用于传递可能需要注意的差错和控制报文。当然,最常见的丢包不会触发任何的ICMP信息,由高层协议来处理。
ICMP报文是在IP数据报内被封装传输的。
IPv4中,协议字段为1表示该报文携带了ICMPv4,ICMP头部与ICMP数据全都附在IPv4头部之后。
而IPv6中,该字段应当是扩展包头的一部分,“下一个头部”字段为58,说明下一个头部是一个ICMPv6报头。
ICMP报文可分为两类:差错报文和信息类报文。
tracert/traceroute工具使用的就是差错报文,通过设置报文的TTL字段从1开始递增,可以逐步打印线路上所有的路由站点。
而ping工具则是使用的信息类报文,这也是最为常用的ICMP报文对(回显请求和回显应答)。
IPv4中的学习路由器的一种方式是路由器发现,通过使用一对ICMPv4信息类报文,设置TTL为1,对本地网络的所有主机组播地址进行组播,这样回显后就能得知本地子网中的所有邻居路由器。
IMCPv6的细节在这里就省略掉了。

用户数据报协议和IP分片

UDP的特性

UDP是一种保留消息边界的简单的面向数据报的传输层协议。它不提供差错纠正、队列管理、重复消除、流量控制和拥塞控制,但它提供差错检测(含校验和)。

UDP格式


其中UDP的检验和检验范围包含12字节的伪头(也含数据部分),计算方式仍然是16位的Internet校验和(16位字的反码和的反码)。
值得注意的是,无论是IPv4的12字节的伪头,还是IPv6的40字节的伪头,都仅仅用于校验和的计算,伪头从来不会出现在报文中被传送出去。

Teredo作为一种通过IPv4网络隧道传输IPv6的技术,方法是将IPv6数据包置于UDP/IPv4数据报的负载区里。其技术细节见【RFC3056】。

IP分片

链路层通常对可传输的每个帧的最大长度有一个上限,为了保持IP数据报与链路层细节的一致,IP引入了分片和重组机制。当IP层接收到一个要发送的数据报时,先比较该数据报大小与MTU大小,若太大则进行分片。
值得注意的是:IPv4中的分片可以在原始发送主机和端到端路径上的任何中间路由器上进行;但IPv6中的分片只在源主机进行。
而一旦一个IP数据报被分片了,直到它到达最终目的地才会被重组,这个过程叫做透明分片。
这样做的原因是:
1.同一数据包的不同分片可能经由不同路径到达相同的目的地,无法在中间重组。
2.在网络中不进行重组能减轻路由器的负担。
对于每一个IP分片来说,它相对于IP负载的起始位置的偏移量由IP头中的偏移量字段给出。计算方式:偏移量*8等于相对于IP负载起始位置的偏移(不含头部)。
而当前IP数据报是否已拼装完成需要依靠MF字段标识该片是否是IP数据报的最后一片。
如果任何一个分片丢失,整个数据报就丢失了。

名称解析和域名系统

使用IP地址来识别参与分布式应用的主机是相当繁琐的。因此互联网支持使用主机名称(host names)来识别主机,而主机名称到IP地址的映射过程由DNS完成。
DNS(域名系统)是一种分布式数据库,作为Internet上的一个应用程序运行。
通常,为了运行效率考虑,大部分的名称服务器会缓存最近被询问过的映射条目,以便下一次进行访问时能够直接从缓存中读取。
由于在计算机网络课程设计中已设计过DNS服务器,DNS的更多细节就不再详述

传输控制协议(TCP)

TCP提供的服务

虽然TCP与UDP同样作为传输层协议,都使用相同的网络层,但TCP给应用程序提供了一种面向连接的、端到端的、可靠的字节流服务(无消息边界)

TCP报文格式

在TCP中,一个IP地址和端口号的组合被称为一个套接字(socket),每个TCP连接由一对套接字唯一地标识。
序列号字段表示当前发送报文段的第一个字节在整个数据流中的位置(TCP给每一个字节赋一个序列号,到达2^32-1后循环到0)。
确认序号只有在ACK标志为1时才有效,它表示该确认号的发送方期待接收的下一个序列号(及成功接受的字节序列号加1)。
头部长度表示TCP头的长度/4,无选项时头部长20字节,该字段为5;该字段最长为15,表示头部最长为60字节。
CRW:拥塞窗口减(发送方减低它的发送速率);
ECE:ECN回显(发送方接受到了一个更早的拥塞通告);
URG:紧急指针有效;
ACK:确认号字段有效;
PSH:推送,立即传输该报文,而不再进行等待足够长的报文合并发送;
RST:重置连接(连接取消,经常是因为错误);
SYN:用于初始化一个连接的同步序列号;
FIN:该报文的发送方已经结束向对方发送数据;
TCP的流量控制由每个端点使用“窗口大小”字段来通告一个窗口大小来完成,限制窗口大小为65535字节。
TCP的16位校验和仍然使用和UDP一样的Internet校验和,并且也包含一个伪头,该校验覆盖伪头、TCP头部和数据部分(UDP也是如此)。
紧急指针字段只有在URG字段被设置时才有效。这个指针是一个必须要加到报文段的序列号字段的正偏移,以产生紧急数据的最后一个字节的序列号。
最常见的选项字段是“最大段大小”字段,称为MSS。连接的每一个端点一般在它发送的第一个报文段(建立连接时,设置SYN的那个段)上指定这个选项。MSS指定该选项的发送者在相反方向上希望接收到的报文段的最大值。
其它一些常见选项包括SACK、时间戳和窗口缩放。

TCP的应用

TCP的应用包括HTTP、SSH/TLS、NetBIOS、Telnet、FTP以及电子邮件,还有多种分布式文件共享程序(如BitTorrent,Shareaza)。

TCP连接管理

TCP是一种面向连接的单播协议,发送数据之前,通信双方必须在彼此间建立一条连接,连接建立过程中,通信双方需要交换一些选项。

TCP连接建立-三次握手

1.主动开启者(通常称为客户端)发送一个SYN报文段(即一个在TCP头部的SYN位字段置位的TCP、IP数据包),并指明自己想要连接的端口号和它的客户端初始序列号(记做x)。通常客户端还会借此发送一个或多个选项。
2.服务器也发送自己的SYN报文段作为回应,并包含了它的初始序列号(记做y),此外为了确认客户端的SYN,服务器将其seq包含的x数值加1后作为返回的ack。因此,每发送一个SYN,序列号就会自动加1,这样如果出现丢失,该SYN段将会重传。
3.为了确认服务器的SYN,客户端将y的数值加1后作为返回的ACK数值。
三次握手的目的不仅在于让通信双方了解一个连接正在建立,还在于交换初始序列号和利用数据包的选项承载特殊的信息。

TCP连接释放-四次挥手

连接的任何一方都可以发起一个关闭操作。传统的情况下,发起关闭连接的通常是客户端(例如系统调用close())。TCP协议规定通过发送一个FIN段来发起关闭操作,只有当连接双方都完成关闭操作后,才构成一个完整关闭。
1.连接的主动关闭者发送一个FIN段指明接收者希望看到的自己当前的序列号(记做u)。事实上,FIN段还包含一个ACK用于确认对方最近一次发来的数据(记做v)【图中未画出】
2.连接的被动关闭者将u的值加1作为响应的ACK值,以表明它已经成功收到了主动关闭者发送的FIN。此时上层的应用程序会被告知连接的另一端已经提出了关闭请求,通常,这将导致应用程序发起自己的关闭操作。接着,被动关闭者将身份转换为主动关闭者,并发送自己的FIN,该段seq仍为v(若中间又发送了其他数据,则序号顺延)。
3.为了完成连接的关闭,最后发送的报文段还包含一个ACK用于确认上一个FIN,值得注意的是,如果出现FIN丢失的情况,那么发送方将重新传输直到接收到一个ACK确认为止。

为什么建立连接是三次报文交换,而释放连接是四次?

因为释放连接时有一段时间处于半关闭状态。有时有这样的需求:在A提请关闭连接时,B尚有数据未发送完毕。因此当一方接收到一个FIN报文后,这仅仅意味着:对方不会再向本机发送数据,但并不意味着本机到对方的数据发送立即停止。事实上这段时间仍然可以完成数据的单方向传送,在FIN报文的接收方也决定彻底断开这个连接时,才会返回一个FIN报文,向对方提请断开反方向的连接。

为什么建立连接是三次握手而不是两次?

网上给出的最常见的解释是:
若是两次握手,那么可能会产生不可避免的死锁:当客户端发起一个SYN请求,服务器会返回一个ACK确认该请求,然后建立单方向连接。此时若该ACK丢失,那么客户端将会无法得知服务器是否准备好。这种情况下,客户端不会建立反方向的连接,这将导致客户端一直等待ACK,而服务器端则在一直等待客户端发送数据,造成死锁。
这个解释问题在于:客户端不会一直傻傻的等待ACK,当一段时间ACK没有收到,它会认为服务器端没有收到自己发送的SYN请求,因此超时后会选择重发SYN,而不断重发的SYN中,总会有ACK返回,死锁自然解除。因此这个解释是不太令人信服的。

特南鲍姆在《计算机网络》中给出的一个例子是:
当客户端发起一个SYN请求,然而由于网络问题,超时未得到回应,于是客户端重新发起一个SYN请求,服务器端接收到了该SYN请求,建立起一个连接。但某个时候旧的请求绕了远路一段时间后才被服务器端接收到。
网上的一种看法是:
若是两次握手,那么服务器接收到旧的SYN请求后会响应一个ACK,两端连接建立完成。但由于客户端并不认为这个请求是有效的,则根本不会理睬返回的ACK,于是服务器一直等待客户端发送数据,而客户端不理睬服务器,这将造成资源的极大浪费。
这个问题在于:既然假设了两次握手就能建立一个连接,那么客户端只要收到了ACK确认,就没有义务再次检验这个请求是否是旧的。它将像下一种看法一样开启这条连接的另一副本(即不只是建立了单方面连接,在第一次握手后服务器端建立单方面连接,第二次握手后客户端不会是close状态,而是建立起反方向连接,这导致建立起一个完整TCP连接的副本)。
特南鲍姆的《计算机网络》看法是:
若是两次握手,那么服务器接收到旧的SYN请求后会响应一个ACK,两端连接建立完成。这将开启了一个新的连接,这个连接是之前发起连接的另一个实例(由于四元组相同),这将会导致两个连接可能同时存在,可能导致一个消息被重复发送。
我认为这种看法是合理的,因为为了避免序号预测攻击,每一次连接前会商定初始序列号,由于我们假定是两次握手,那么对于一个旧的SYN请求,客户端没有义务进行验证它的初始序列号。但我们加了初始序列号这个功能,就是为了避免旧的SYN请求有效,客户端应当对其进行验证。这导致初始序列号机制与两次握手机制出现两难,因此两次握手一定是不合理的。

接着我们论述为什么三次握手可以解决这一问题:
为了解决延迟报文段被视为有效的问题,我们引入了可变的初始序列号机制。因此当服务器接收到一个旧的请求时,它首先并不知道这个请求是否是旧的,因此仍然回复一个ACK确认该SYN段,但客户端发现该ACK对应的ack字段期望的值(初识序列号加1)对应的是一个已经过时的请求,因此不会建立单方面连接,并向服务器端发送第三次握手的通知(类似NAK),此时服务器端了解自己是被一个已经过时了的请求欺骗了,于是释放自己单方面的连接。最终结果是两个单方面连接都未建立,也即连接未建立,因此也没有浪费资源。

此外,我们还有关于为什么是三次握手而不是两次握手的原因补充:
为了实现可靠数据传输,TCP协议的通信双方,都必须维护一个序列号,以标识发送出去的数据包中,哪些是已经被对方收到的。三次握手的目的不仅在于让通信双方了解一个连接正在建立,还在于交换并确认初始序列号。如果只是两次握手,至多只有连接发起方的起始序号能被确认,另一方选择的序列号得不到确认。

附:这里仍有一个问题尚未解决:为了区分新旧SYN请求,相邻两次要使用不同的初识序列号,但就使用Wireshark抓包的结果来看,每次SYN(包括重发的)都是使用0作为初始序列号,这相当令人困惑

TCP半关闭

事实上,发送一个FIN报文的含义是:我已经完成了数据的发送工作,并发送一个FIN给对方,但我仍然希望接收来自对方的数据直到它也发送一个FIN给我。(API中的close()会关闭一条连接的两个传输方向,但shutdown()将完成上述工作)

同时打开与关闭

同时打开的情况下,连接建立所需的报文段由三个变为四个。

同时关闭的情况下,连接释放仍需四个报文段,但顺序发生交叉。

初始序列号

在发送用于建立连接的SYN之前,通信双方会选择一个初始序列号。初始序列号会随着时间而改变,因此每一个连接都拥有不同的初始序列号。
由于一个TCP连接是被一对端点所唯一标识的,其中包括两个IP地址与两个端口号所构成的四元组,因此即便是同一个连接也会出现不同的实例。
问题:如果连接由于某个报文段的长时间延迟而被关闭,然后又以相同的四元组被重新打开,那么可以相信延迟的报文段又会被视为有效数据重新进入新连接的数据流中。
解决方案:让连接实例的序列号彼此不同就能区分出不同的连接实例。
TCP的安全脆弱性:如果选择合适的序列号、IP地址和端口号,那么任何人都能伪造出一个TCP报文段,从而威胁TCP的正常连接。
尝试解决方案:现代操作系统通常使用半随机的方法选择初始序列号。Linux基于时钟针对每一个连接设置随机的偏移量,随机偏移量是在连接标识(四元组)的基础上利用加密散列函数得到的,散列函数的输入每隔5分钟就会改变一次。

TCP选项

1.最大段大小选项
最大段大小指TCP协议所允许的从对方接收到的最大报文段,因此也是通信对方在发送数据时能使用的最大报文段。该值只记录TCP数据的字节数而不包括TCP头部,建立连接时,通常要在SYN报文段的MSS选项中说明自己允许的最大段大小,未指明时,该值默认是536字节,536+20+20=576恰与任何主机能处理至少576字节的IPv4数据报对应。
2.选择确认选项
SYN报文中可携带“允许选择确认选项”,而后每一个报文段中都可以包含选择确认选项。该选项用于指明哪些数据块收到了而哪些数据块没有收到,以便于TCP的快速选择重传。
3.时间戳选项与防回绕序列号
时间戳的第一个用途是用于估计RTT
第二个用途是解决序列号回绕的问题,接收者可将时间戳看作一个32位的扩展序列号,收到报文段时不仅查看序列号还验证时间戳,若收到报文段的时间戳小于当前时间戳,说明这是一个过时的延迟的报文段。

TIME_WAIT 状态

该状态也称2MSL等待状态。在该状态中,TCP将会等待两倍于最大段生存期(MSL)的时间。
那么,究竟为什么TIME_WAIT状态下要等待两个MSL时间呢?
首先我们先讨论为什么客户端发送ACK后不能直接关闭,试想这样的情况:第四次握手时发送的ACK由于某种原因丢掉了,服务器端迟迟收不到ACK,于是认为对方没有收到第三次握手时的FIN与ACK报文,超时重发FIN与ACK报文。若客户端发送ACK后立即关闭,客户端将无法收到重发的FIN+ACK,也无法再次发送ACK报文,因此不能立即关闭。
接着我们再讨论为什么是2MSL,试想这样的情况:前一次连接成功释放后,我们立即建起一个新的连接(四元组可能相同),而原本滞留在网络中的一些报文可能在此时到达造成困扰。为了避免这种情况,我们应当确保连接释放结束时,所有的包都已经失效。因此等待2MSL,待网络中该次连接所有的报文段都已消失,可以避免旧请求对新连接的影响。

超时与重传

TCP有两套独立的机制来完成重传,一是基于时间,二是基于确认信息的构成。后者通常比前者更高效。
TCP在发送数据时会设置一个计时器,若至计时器超时仍未收到确认消息,则会引发相应的超时或基于计时器的重传操作,计时器超时称为重传超时(RTO)。
另一种方式被称为快速重传,通常发生在没有延时的情况下。若TCP累计确认无法返回新的ACK,或者当ACK包含的选择确认消息(SACK)表明出现失序报文段时,快速重传会推断出现丢包。

设置重传超时

TCP超时和重传的基础是怎样根据给定连接的RTT设置RTO(RTT估计由时间戳选项给出),RTO设置得当是保证TCP性能的关键。
Jacobson给出了一种算法:
SRTT = (1-α) SRTT + α (RTT)
RTTVAR = (1-β) RTTVAR + β (| RTT - SRTT |)
RTO = SRTT + 4 (RTTVAR)
一般α取1/8,β取1/4
初始值取SRTT=RTT,RTTVAR=RTT/2

重传二义性与Karn算法

在测量RTT样本的过程中若出现重传,就可能导致某些问题。假如一个包的传输出现超时,该数据包会被重传,接着收到一个确认信息。那么该信息是对第一次还是第二次传输的确认就存在二义性。
Karn算法:
当收到重复传输(即至少重传一次)数据的确认信息时,不进行该数据包的RTT测量,可以避免重传二义性的问题。另外,对该数据包之后的包采取退避策略(每当重传计数器出现超时,退避系数加倍)。仅当收到未经重传的数据时,该RTT才用于计算RTO。

快速重传

快速重传机制不再依赖于计时器,而是基于接收端的反馈信息来引发重传。因此与超时重传相比,快速重传能更加及时有效地修复丢包情况。
当失序数据到达时,重复ACK应立即返回,不能延时发送。原因在于使发送端尽早得知有失序报文段,并告诉其空缺在哪。
即便后面的数据包已经收到,但前面有一段一直未收到,于是每次收到其后的段,都会返回对丢失段的确认。发送方等待一定数目的重复ACK(该数目称为重复ACK阈值),发送方此时不必等待丢失段的计数器超时,而是直接开始重传该段。
由于该过程只需要接收到一定数量的(一般为3)重复ACK,就会不等待计数器超时而直接开始重传。因此该机制被称为快速重传。同时,重复的ACK推断的丢包通常与网络拥塞有关,因此快速重传通常伴随拥塞控制机制。

快速选择重传

数据包的丢失常常导致多个空缺,而原本的快速重传只针对最前面的丢失段进行重复确认。
快速选择重传支持在一个ACK中使用SACK选项,通知三到四个空缺的段。因此利用SACK能在一个RTT时间内填补多个空缺,显著加速了空缺填补,且能减少不必要的重传。
有时我们也会用重复SACK(DSACK)解决伪超时问题

TCP数据流与窗口管理

延时确认

在许多情况下,TCP并不对每个到来的数据包都返回ACK,利用TCP的累计ACK就能实现该功能。累计确认可以允许TCP延迟一段时间发送ACK,以便将ACK与相同方向上需要传的数据结合发送。这种捎带传输的方法经常用于批量数据传输,可以一定程度上减轻网络负载。

Nagle 算法

高频次小包的发送会显著影响系统性能,由于小包的数据部分很少,因此固定头部(20字节IP头,20字节TCP头)对于该包来说是相当高的网络传输代价。该问题对局域网不会有很大影响,但对于广域网,这会显著加重拥塞,严重影响网络性能。
John Nagle提出了一种算法,现称为Nagle算法:
当一个TCP连接中有在传数据(已发送但还未收到确认),小的报文段(长度小于SMSS)就不能被发送,直到所有的在传数据都收到ACK,并且收集这些小数据,将其整合到一个报文段中发送。这种方法迫使TCP遵循停等协议(只有等接受到所有在传数据的ACK后才能继续发送)。
该算法使单位时间内发送的报文段数目显著下降,而RTT控制着发包速率(由于RTT越小ACK返回越快)。

滑动窗口

TCP使用可变滑动窗口来实现流量控制,TCP的客户端和服务器交互作用,互相提供数据流的相关信息,包括报文段序列号,ACK号和窗口大小。TCP头部的窗口大小字段表明接收端可用缓存空间的大小,长度为16位。
随着时间的推移,当接收到返回的数据ACK,滑动窗口也随之右移。窗口两端的相对运动使得窗口增大或减小。
下面是三个术语用于描述窗口左右边界的运动:
1.关闭:即窗口左边界右移,当已发送数据得到ACK确认时,窗口会减小。
2.打开:即窗口右边界右移,使得可发送数据量增大。当已确认数据得到处理,接收端可用缓存变大,窗口也随之变大。
3.收缩:即窗口右边界左移,主机需求并不支持这一做法,但TCP必须能处理这一问题。

每个TCP报文段都包含ACK号和窗口通告信息,TCP发送端可据此调节窗口结构。窗口左边界不能左移,因为它控制的是已经确认的ACK号,具有累积性,不能返回。当得到的ACK号增大而窗口大小保持不变时(通常如此),我们就说窗口向前滑动。若随ACK号增大窗口却减小,则左右边界距离减小。当左右边界相等时,称为零窗口,此时发送端不能再发送数据。这种情况下,TCP发送端开始探测对方窗口,伺机增大提供窗口。
接收端也维护一个窗口结构,该窗口记录了已接收并确认的数据,以及它能接收的最大序列号。只有前面的数据全部被确认了,窗口左边界才能前移,否则通过发送重复ACK或SACK通知发送方要求重发。

零窗口与TCP持续计时器

TCP通过接收端的通告窗口来实现流量控制,该窗口指示了接收端可接受的数据量,当窗口值变为零时,可以有效阻止发送端继续发送,直到窗口恢复非零值。当接收端重新获得可用空间时,会给发送端传输一个“窗口更新”,告知其可继续发送数据。这样的窗口更新通常不含数据(纯ACK),不能保证其传输的可靠性,因此TCP必须有相应措施处理这类丢包。
试想:若一个包含窗口更新的ACK丢失,通信双方就会一直处于等待状态:接收方等待接收数据,发送方等待收到窗口更新告知其可继续发送数据。
为防止这种死锁,发送端会采用一个持续计时器间歇性查询接收端,看其窗口是否已增长。持续计时器会触发“窗口探测”的传输,强制要求接收端返回ACK(其中包含了窗口大小字段)。
窗口探测包含一个字节的数据,采用TCP可靠传输,因此可以避免由窗口更新丢失导致的死锁。当TCP持续计时器超时,就会触发窗口探测的发送。其中包含的一个字节的数据能否被接收,取决于接收端的可用缓存空间大小。

糊涂窗口综合征(SWS)

当出现该问题时,交换的数据段大小不是全长的,而是一些较小的数据段,由于每个报文段中有用数据相对头部信息的比例较小,因此耗费资源也更多,传输效率也更低。
这个问题出现在TCP连接的两端:
1.接收端的通告窗口较小(没有等到窗口变大才通告)
2.发送端发送的数据段较小(没有等待其他数据组合成一个更大的报文段)
其中发送端的问题可用Nagle算法来解决。
下面着重讲控制接收端的Clark算法
对于接收端来说,不应通告小的窗口值。在窗口可增至一个全长的报文段(接收端MSS)或者接收端缓存空间的一半之前,不能通告比当前窗口(可能为0)更大的窗口值。
有两种情况会用到该规则:
1.当应用程序处理接收到的数据后使得可用缓存增大。
2.TCP接收端需要强制返回对窗口探测的响应。

TCP拥塞控制

路由器因无法处理高速率到达的流量而被迫丢弃数据的现象称为拥塞。
针对丢包情况,TCP的第一反应是重传(包括超时重传和快速重传),但当网络出现拥塞崩溃状态时,共用一条网络传输路径的多个TCP连接却需要重传更多的数据包,这会加剧拥塞状况,因此这种情况应当避免。
当拥塞出现时,我们应当减缓TCP发送端的发送速率。然而对于TCP的发送方来说,没有一个明确的方法能够知晓中间路由器的状态,即没有一个明确的信号告知拥塞状况已经发生。除ECN能在丢包前检测拥塞外,典型TCP都只有在断定拥塞发生的情况下才会采取行动,推断是否出现拥塞的信号是查看是否有丢包情况。
我们之前已经看到,TCP可以利用计时器、确认以及选择确认机制来检测丢包情况。
因此下面我们关心的是,当TCP已经确认网络发生拥塞丢包时,除了重传数据包,TCP还做了哪些工作及它如何完成减缓发送速度。

拥塞窗口

发送端维护一个发送窗口,确保发送窗口大小不超过接收端的接收能力和网络传输能力。
其中接收端的接收能力由接收窗口表示,而网络传输能力则由拥塞窗口表示。
接收端通知窗口用awnd表示,拥塞窗口用cwnd表示,发送端的实际窗口W是二者的最小值:
W=min(cwnd,awnd)
W的值不能过大或过小,我们希望其接近带宽延迟积。
实际运行过程中,W的值是随着cwnd与awnd的动态变化而动态变化的。
下面我们讨论TCP的两个核心算法:慢启动和拥塞避免

慢启动

慢启动的目的是:使TCP在用拥塞避免探寻更多可用带宽之前得到cwnd值,以及帮助TCP建立ACK时钟。在传输初始阶段,由于未知网络传输能力,需要缓慢探测可用传输资源,防止短时间内大量数据注入导致拥塞。
通常TCP在建立新连接或重传计时器检测到丢包时会执行慢启动算法,直至到达阈值时,执行拥塞避免算法。
TCP以发送一定数目的数据段开始慢启动,称为初始窗口(IW),IW的初始值设为一个SMSS(发送端的最大段大小),慢启动每接收到一个ACK就执行一次cwnd的增长操作(加一),针对第一次的ACK,发送端会发送2个新报文段,这2个报文段的ACK又会导致4个新报文段的发送。因此cwnd大小呈指数增长。
cwnd会快速增长,帮助确立一个慢启动阈值ssthresh,一旦到达阈值,TCP会进入拥塞避免状态,执行拥塞避免算法。
ssthresh=max(min(cwnd,awnd)/2,2SMSS)
当出现了重传情况,TCP会认为操作窗口超出了网络传输能力范围,慢启动阈值将会变成当前窗口大小的一半(但不小于2
SMSS)。

拥塞避免

一次重传将会确定一个慢启动阈值,当cwnd到达了该阈值后,将会执行拥塞避免算法,cwnd将会随时间线性增长。
cwnd’=cwnd+SMSS*SMSS/cwnd

TCP Tahoe

Tahoe协议版本在连接之初处于慢启动阶段,若检测到丢包,不论由于超时还是快速重传,都会重新进入慢启动状态。有丢包情况发生时,Tahoe简单的将cwnd设为初始值(1SMSS)以达到慢启动目的,直至cwnd增长为ssthresh。
这个问题在于TCP发送方经重新慢启动,回归到的还是未丢包状态(cwnd启动初始值设置过小),这会使得带宽利用率底下。
为解决这一问题,我们介绍快速恢复算法

快速恢复

若是由重复ACK引发的丢包(引发快速重传),cwnd值将被设为上一个ssthresh,而非先前的1SMSS,这种方式使得TCP无需重新慢启动而只要把传输速率减半即可。

这里给出一个二者对比图

TCP Reno

TCP Reno就是加入了快速恢复算法,并得到了广泛应用。
在TCP连接建立之初首先是慢启动阶段(cwnd=IW),ssthresh通常取一较大值(至少为awnd)。当接收到一个ACK,cwnd会相应更新:
cwnd+=SMSS(若cwnd<ssthresh)慢启动
cwnd+=SMSSSMSS/cwnd(若cwnd>ssthresh)拥塞避免
解释:会有cwnd/SMSS个ACK返回,共同导致cwnd加了一个SMSS
当收到三次重复ACK时,会执行以下行为:
1.更新ssthresh为max(min(cwnd,awnd)/2,2
SMSS)。
2.启用快速重传算法,将cwnd设为(ssthresh+3*SMSS)。
3.每接收到一个重复ACK,cwnd值暂时增加1SMSS。
4.每接收到一个好的ACK,将cwnd重设为ssthresh。

ECN

通常TCP推断拥塞产生的唯一方法就是发生丢包现象,TCP除了事后再做出反应外无能为力,然而ECN(显式拥塞通知)可以对经过路由器的数据包进行标记(设置头部的两个ECN标志位),以此得到拥塞状况,并能将拥塞状况报告给端节点。
当数据报被接收时,其中的拥塞标记表明这个包经过了一个拥塞的路由器。当然,发送端而不是接收端才真正需要这些信息,以此降低发送速率。因此,接收端通过向发送端返回一个ACK数据包来通知拥塞状况。
ECN主要在IP层进行操作,也可以应用于TCP协议之外的其他传输层协议。
具体过程如下:
当一个包含ECN功能的路由器经过长时间拥塞,接收到一个IP数据包后,它会查看IP头中的ECN传输能力(ECT)标识。如果有效,负责发送数据包的传输层协议将会开启ECN功能,此时路由器会在IP头设置一个已发生拥塞(CE)标识。
若TCP接收端发现接收到的数据包CE标识被置位,它会将每一个ACK的“ECN回显”位字段置位,直到接收到一个从发送端来的CWR位字段被置位的数据包(说明发送速率已经降低)。

TCP保活机制

一些情况下,客户端和服务器需要了解什么时候终止进程或者与对方断开连接。而在另一些情况下,虽然应用进程之间没有任何数据交换,但仍需要通过连接保持一个最小的数据流。
TCP保活机制就是为了上述两种情况而设计的。
保活机制是一种在不影响数据流内容的情况下探测对方的方式。它是由一个保活计时器实现的。当计时器被激发,连接一端将发送一个保活探测报文,另一端接收报文的同时会发送一个ACK作为响应。

描述

保活功能在默认情况下该关闭,需要时TCP任何一端都可以请求打开这一功能。如果在一段时间内连接处于非活动状态,开启保活功能的一端将会向对方发送一个保活探测报文。若发送端没有收到响应报文,那么经过一个提前设置好的保活时间间隔,将继续发送保活探测报文,直到发送探测报文的次数达到保活探测数,这时对方主机将被确认为不可到达,连接也将被中断。
保活探测报文是一个空报文段(或只包含1字节)。它的序列号等于对方主机发送的ACK报文的最大序列号减1。因为这一序列号的数据段已经被成功接收,所以不会对到达的报文段造成影响,但探测报文返回的响应可以确定连接是否仍在工作。探测及其响应报文都不包含任何新的有效数据,当他们丢失时也不会进行重传。
值得注意的是:仅凭一个没有被响应的探测报文不能判断连接是否已经停止工作。这就是为什么保活探测数需要被提前设置的原因。
TCP保活功能工作过程中,开启该功能的一端会发现对方处于以下四种状态之一:
1.对方主机仍在工作,并且可以到达。对方的TCP响应正常,并且请求端也知道对方在正常工作。请求端将保活计时器重置(重新设定为保活时间值),如果在计时器超时前有应用程序通过该连接传输数据,那么计时器将再次被设定为保活时间值。
2.对方主机已经崩溃,包括已经关闭或者正在重新启动。这时对方的TCP将不会响应。请求端不会收到响应报文,并在经过保活时间间隔指定的时间后超时。超时前,请求端会持续发送探测报文,一共发送保活探测数指定次数的探测报文,如果请求端没有收到任何探测报文的响应,那么它认为对方主机已经关闭,连接也将被断开。
3.客户主机崩溃并且已重启。在这种情况下,请求端会收到一个对其保活探测报文的响应,但这个响应是一个重置报文段,请求端将会断开连接。
4.对方主机仍在工作,但是由于某些原因不能到达请求端,这种情况同2,TCP不能区分情况2和情况4,结果都是没有收到探测报文的响应。
请求端不必担心对方主机正常关闭然后重启的情况。当系统关机时,所有的应用程序也会终止,这会使对方的TCP发送一个FIN,请求端接收到FIN后,会向请求端进程报告文件结束,并在检测到该状态后退出。

至此,我们已简单讨论了TCP / IP协议栈的大部分内容,HTTP及HTTPS的内容在《TCP/IP详解·卷一:协议》中没有这部分,因而我们还缺少一部分应用层及网络安全部分的介绍,应用层的内容将会在后面的博客中涉及

《TCP/IP详解·卷1:协议》随笔(已完结)相关推荐

  1. TCP/IP详解 卷1:协议 学习笔记 第十六章 BOOTP:引导程序协议

    一个无盘系统在不知道自身IP地址情况下,进行系统引导时能通过RARP协议获取它的IP地址,使用RARP会有两个问题:(1)IP地址是返回的唯一结果:(2)RARP使用链路层广播,RARP请求不会被路由 ...

  2. 《TCP/IP详解卷1:协议》第6章 ICMP:Internet控制报文协议-读书笔记

    章节回顾: <TCP/IP详解卷1:协议>第1章 概述-读书笔记 <TCP/IP详解卷1:协议>第2章 链路层-读书笔记 <TCP/IP详解卷1:协议>第3章 IP ...

  3. 《TCP/IP详解卷1:协议》第3章 IP:网际协议(2)-读书笔记

    章节回顾: <TCP/IP详解卷1:协议>第1章 概述-读书笔记 <TCP/IP详解卷1:协议>第2章 链路层-读书笔记 <TCP/IP详解卷1:协议>第3章 IP ...

  4. 《TCP/IP详解 卷1:协议》第4章 ARP:地址解析协议

    4.1 引言 本章我们要讨论的问题是只对TCP/IP协议簇有意义的IP地址.数据链路如以太网或令牌环网都有自己的寻址机制(常常为48 bit地址),这是使用数据链路的任何网络层都必须遵从的.一个网络如 ...

  5. 《TCP/IP详解卷1:协议》读书笔记

    <TCP/IP详解卷1:协议>读书笔记 - QingLiXueShi - 博客园 https://www.cnblogs.com/mengwang024/p/4425834.html &l ...

  6. 《TCP/IP详解卷1:协议》第5章 RARP:逆地址解析协议---读书笔记

    <TCP/IP详解卷1:协议>第5章 RARP:逆地址解析协议---读书笔记 1.引言 具有本地磁盘的系统引导时,一般是从磁盘上的配置文件中读取IP地址.但是无盘机,如X终端或无盘工作站, ...

  7. 《TCP IP 详解卷1:协议》阅读笔记 - 第十章

    阅读须知:笔记为阅读<TCP IP 详解卷1:协议>后摘抄的一些知识点,其间也有加入一些根据英文原版的自己翻译和结合网上知识后的理解,所以有些段落之间并不能够串联上或者知识点与书上略有差别 ...

  8. TCP/IP详解卷1 - wireshark抓包分析

    TCP/IP详解卷1 - 系列文 TCP/IP详解卷1 - 思维导图(1) TCP/IP详解卷1 - wireshark抓包分析 引言 在初学TCP/IP协议时,会觉得协议是一种很抽象的东西,通过wi ...

  9. 《TCP/IP详解卷1》学习小结(一)------链接层

    开始学习<TCP/IP详解卷1>这本著作,每一章都要写一篇学习小结.        一.  总述 链接层位于整个网络协议suite的最低一层,与硬件关系密切,比如以太网,token rin ...

最新文章

  1. 医疗信息化、医学、医院管理、医疗器械资料下载
  2. div+css中设置了float属性后如何让外层的高度随着内层的高度大小自动调整
  3. 转-D3D中的四元数
  4. 编程之美-字符串移位问题方法整理
  5. Eclipse+Maven创建webapp项目
  6. DeepFakes天敌来了!伯克利紧急研发“火眼金睛”防伪克星
  7. 量化金融第一步获取市场数据 (Python Tushare)
  8. 都说dlib是人脸识别的神器,那到底能不能识破妖怪的伪装?
  9. 关键字restrict简介
  10. 防火防盗竟防不了网络攻击智能摄像机的网络安全怎么办?
  11. 惠普ns1005w使用说明_惠普 NS1005w 多功能一体机解析:15秒智能闪充 + 全功能手机操控...
  12. System.Data.Entity.Core.MetadataException:“Unable to load the specified metadata resource.”
  13. Linux系统密码忘记教程
  14. 身份证号码识别(python)
  15. 微信公证号授权给微信开放平台(第三方平台)开发流程 PHP (基于laravel框架开发)
  16. centos安装图形化界面及vnc-server连接
  17. 统考计算机三次没过怎么办,网络教育统考一直没过怎么办
  18. Google Chorme
  19. 计算机 文笔不好的论文,文笔差怎么写出好文章
  20. 用户登录和注册界面的实现

热门文章

  1. 我在QQ上偷偷望着你
  2. 百度网页打不开的解决方法之一
  3. 红米笔记本linux,Redmi首款AMD笔记本将加入全新小米互传
  4. 第七章、模型详解 -- 多表查询
  5. 数据结构---队列及其应用
  6. Interger对象源码解析
  7. 修改魅族和小米状态栏的文字颜色
  8. miui从服务器检索信息时出错,防盗大战 解析魅族/小米查找手机功能
  9. 雷军:我的天赋无数,但你能学到的只有一种
  10. posenet怎么玩?真人录制火柴人,骚气起来! | Mixlab 技术前沿