首页 > 代码库 > 《TCP/IP详解》读书笔记

《TCP/IP详解》读书笔记

本书以UNIX为背景,紧贴实际介绍了数据链层、网络层、运输层

 
一、整体概念
 
1.各层协议的关系,只讨论四层
各层常见的协议:
 
网络层协议:IP协议、ICMP协议、ARP协议、RARP协议。
传输层协议:TCP协议、UDP协议。
应用层协议:FTP、Telnet、SMTP、HTTP、RIP、NFS、DNS。
 
STMP、POP3、IMAP都是邮件服务协议,STMP主要负责发送和转发,POP3和IMAP负责接收
 
具体如下:
 
2.各层之间的数据
 
二、数据链路层
 
 
三、IP层
 
1.报文格式
 
●版本(Version)字段:占4比特。用来表明IP协议实现的版本号,当前一般为IPv4,即0100。
 
●报头长度(Internet Header Length,IHL)字段:占4比特(以4字节为单位)。是头部占32比特的数字,包括可选项。普通IP数据报(没有任何选项),该字段的值是5,即160比特=20字节。此字段最大值为60字节。
 
●服务类型(Type of Service ,TOS)字段:占8比特。其中前3比特为优先权子字段(Precedence,现已被忽略)。第8比特保留未用。第4至第7比特分别代表延迟、吞吐量、可靠性和花费。当它们取值为1时分别代表要求最小时延、最大吞吐量、最高可靠性和最小费用。这4比特的服务类型中只能置其中1比特为1。可以全为0,若全为0则表示一般服务。服务类型字段声明了数据报被网络系统传输时可以被怎样处理。例如:TELNET协议可能要求有最小的延迟,FTP协议(数据)可能要求有最大吞吐量,SNMP协议可能要求有最高可靠性,NNTP(Network News Transfer Protocol,网络新闻传输协议)可能要求最小费用,而ICMP协议可能无特殊要求(4比特全为0)。实际上,大部分主机会忽略这个字段,但一些动态路由协议如OSPF(Open Shortest Path First Protocol)、IS-IS(Intermediate System to Intermediate System Protocol)可以根据这些字段的值进行路由决策。
 
●总长度字段:占16比特。指明整个数据报的长度(以字节为单位)。最大长度为65535字节。
 
●标识字段:占16比特。用来唯一地标识主机发送的每一份数据报。通常每发一份报文,它的值会加1。
 
●标志位字段:占3比特。标志一份数据报是否要求分段。
 
●段偏移字段:占13比特。如果一份数据报要求分段的话,此字段指明该段偏移距原始数据报开始的位置。
 
●生存期(TTL:Time to Live)字段:占8比特。用来设置数据报最多可以经过的路由器数。由发送数据的源主机设置,通常为32、64、128等。每经过一个路由器,其值减1,直到0时该数据报被丢弃。
 
●协议字段:占8比特。指明IP层所封装的上层协议类型,如ICMP(1)、IGMP(2) 、TCP(6)、UDP(17)等。
 
●头部校验和字段:占16比特。内容是根据IP头部计算得到的校验和码。计算方法是:对头部中每个16比特进行二进制反码求和。(和ICMP、IGMP、TCP、UDP不同,IP不对头部后的数据进行校验)。
 
●源IP地址、目标IP地址字段:各占32比特。用来标明发送IP数据报文的源主机地址和接收IP报文的目标主机地址。
可选项字段:占32比特。用来定义一些任选项:如记录路径、时间戳等。这些选项很少被使用,同时并不是所有主机和路由器都支持这些选项。可选项字段的长度必须是32比特的整数倍,如果不足,必须填充0以达到此长度要求。
 
2.ip分片
 
链路层具有最大传输单元MTU这个特性,它限制了数据帧的最大长度,不同的网络类型都有一个上限值。以太网的MTU是1500。如果IP层有数据包要传,而且数据包的长度超过了MTU,那么IP层就要对数据包进行分片(fragmentation)操作,使每一片的长度都小于或等于MTU。我们假设要传输一个UDP数据包,以太网的MTU为1500字节,一般IP首部为20字节,UDP首部为8字节,数据的净荷(payload)部分预留是1500-20-8=1472字节。如果数据部分大于1472字节,就会出现分片现象。
 
传输层的首部只出现在第一片数据中,ip的每个片段都包含一个首部,其中有一个偏移量属性,表示该片段在整个数据中的位置
 
TCP也会进行分片,TCP分段产生原因是MSS(TCP数据包每次能够传输的最大数据分段),TCP协议在实现的时候往往用MTU值代替(需要减去IP数据包包头的大小20Bytes和TCP数据段的包头20Bytes)所以一般MSS值1460,故采用TCP协议进行数据传输,是不会造成IP分片的。若数据过大,只会在传输层进行数据分段,到了IP层就不用分片。而我们常提到的IP分片是由于UDP传输协议造成的,因为UDP传输协议并未限定传输数据报的大小。
 
3.路由器内部选路协议
 
路由器内部选路协议即是在路由器路由表给定的情况下进行选路
路由器或者主机将会用如下的方式来处理某一个IP数据包:
 
如果IP数据包的TTL(生命周期)以到,则该IP数据包就被抛弃。
 
a.搜索匹配的主机地址:搜索路由表,寻找与目的IP地址完全匹配的表项(网络号和主机号都匹配)。如果找到,则把报文发送给指定的下一跳路由器。
b.搜索匹配的网络地址:搜索路由表,寻找与目的IP地址的网络号相匹配的表项。如果找到,则把报文发送给指定的下一跳路由器。
c.搜索默认表项:寻找默认路由表项。如果找到,则把报文发送给表项指定的下一跳路由器。
 
4.路由器外部选路协议
 
路由器内部选路协议即是更新路由表
DV和LS
 
5.ICMP协议
 
为提高IP数据包交付成功的机会,网际层使用了因特网控制报文协议ICMP(Internet Control Message Protocol)。ICMP允许主机或路由器报告差错情况和提供有关异常情况的报告,ICMP是因特网标准协议,但不是高层协议,而是网络层协议。ICMP报文作为IP层数据包的数据,加上数据包的首部,组成数据包发送出去。
ICMP主要完成以下2个功能:
 
(1)不能到达目的地警告:如果网络上的主机检测到其目的是不可达的,不管是因为目的地址与网络上的机器操作不匹配,还是因为连接错误,它都将向发送方发送一个“目的地址不可达”的报文。
 
(2)重定向路由:网关发送ICMP重定向报文,以告诉发送方使用另一个网关。比如,网关A接收来自某主机的一个报文,该报文要发送到某一指定的网络,如果网关A知道主机如果使用网关B能够更快地到达目的网络,网关A就将发送一个ICMP重定向报文,告诉发送主机将报文发送到网关B。
 
这种机制使得所有智能特性放在的路由器,主机只要通过重定向报文逐步学习来完善路由器选路
 
6.IGMP协议
 
它让一个物理网络上的所有系统知道主机当前所在的多播组。多播路由器需要这些信息以便知道多播数据报应该向哪些接口转发。正如ICMP一样, IGMP 也被当作IP 层的一部分。IGMP报文通过IP数据报进行传输。
 
 
 
 
四、运输层
 
1.tcp首部格式
 
 
序列号用来标识从TCP发端向TCP收端发送的数据字节流,它表示在这个报文段中的第一个数据字节。反过来,确认序列号是表示TCP发端期望从TCP收端收到的下一个字节。
 
首部长度给出首部中32bit字的数目,跟IP首部一样,TCP最多有60字节的首部
 
接下来是6个标志比特,它们中的多个可以被同时设置为1:
URG:紧急指针有效,与后面的紧急指针结合起来
ACK:确认序号有效
PSH:接收方尽快将这个报文段交给应用层
RST:重建连接
SYN:同步序号用来发起一个连接
FIN:发端完成发送任务,将要关闭连接
 
检验和的计算方法和UDP中的检验和一样,也要加上伪首部,也要填充奇数字节,与UDP不同的是,TCP强制要求计算检验和,而UDP的检验和是可选的。
 
窗口大小表明接收端当前的接收能力,以字节为单位,16位窗口限制了最大值为65535字节,在选项字段中,有一个窗口刻度选项,允许这个值按比例放大。
 
紧急指针是一个正的偏移量,和序号中的值相加表示紧急指针最后一个字节的序号。
 
选项字段可以包括最长报文大小(MSS),这是最常见的可选字段。每个连接方通常都在通信的第一个报文段中指明这个选项,表明本端所能接收的最大长度的报文段;还有上面我们提到的窗口扩大选项以及时间戳选项,我们将在后面看到时间戳选项的作用。
 
 
2.UDP格式
 
offset (bits) 0 – 15 16 – 31
0 Source Port Number Destination Port Number
32 Length Checksum
64+  
Data
 
 
3.三次握手
这里之所以需要三次是因为,无论是客户端还是服务端,都需要对自己发出的包文进行确认
 
状态转移图:
4.TCP的传输控制
 
a.流量控制:根据发送方和接收反方的缓存空间,控制端到端的流量,以免会产生发送过快导致收端溢出,或者因收端处理太快而浪费时间的状态。用的策略是:滑动窗口,以字节为单位,与网络大环境无关
 
滑动窗口有两种操作:
 
合拢:表示已经收到相应字节的确认了(左边界向右边界移动)
展开:表示允许缓存发送更多的字节(右边界向右移动)
 
某些时候,由于发端或收端的数据很慢,会引起大量的1字节数据窗口,浪费很多资源,有以下两种情况:
 
(1)发端的进程产生数据很慢时候,时不时的来个1字节数据,那么TCP就会1字节1字节的发送,效率很低。
解决方法(Nagle算法):TCP连接上只能有一个未被确认的小分组,在该分组确认前不能发送其它小分组
  • 将第一块数据发出去
  • 然后等到发送缓存有足够多的数据(最大报文段长度),或者等到收端确认的ACK时再发送数据。
  • 重复b的过程
(2)收端进程由于消耗数据很慢,所以可能会有这么一种情况,收端会发送其窗口大小为1的信息,然后有是1字节的传输
解决办法(2种)
  • Clark方法:在接收缓存的一半变空,或者有足够空间放最大报文长度之前,宣告接收窗口大小为0
  • 推迟确认:在对收到的报文段确认之前等待到足够的接收缓存,或者等待到一个时间段
 
 
b.拥塞控制:根据网络的拥塞情况,控制两端的流量,拥塞的三种策略:慢启动(指数增大),拥塞避免(加法增大),拥塞检测(除2减少,或叫做乘法减少),与网络大环境有关
 
拥塞窗口机制
 
拥塞窗口:发送方使用的流量控制,每收到一个ACK,就增加一个报文段
通告窗口:接收方使用的流量控制
 
发送方取拥塞窗口和通告窗口的最小值最为发送上限
 
(1)慢启动:指数增大
/* ssthresh是慢开始门限,cwnd是拥塞窗口 */
cwnd = 1;(1表示一个MSS报文段,滑动窗口是一个字节)
while ( cwnd < ssthresh )
    if( 发出的报文段确认 )
       cwd *= 2;
 
(2)拥塞避免:加法增大
当到达ssthresh之后,就是加法阶段了,每收到一个确认,cwd += 1;       
 
(3)拥塞检测:乘法减少(除2减少)
当报文需要重传时,说明拥塞可能发生了,由于重传有2种情况,所以也分两种处理
 
  由于没有收到ACK,超时重传,这是拥塞的可能性比较大,如下做强反映调整
  • ssthresh /= 2;
  • cwnd = 1;
  • 重新慢启动过程
  由于收到3个重复的ACK的重传,采取弱反映
  • ssthresh /= 2;
  • cwnd = ssthresh;
  • 开始拥塞避免过程
 
c.差错控制:保证数据:按序,没有差错,没有部分丢失,没有重复的交给应用层。方法就是:校验和,确认,超时重传
 
(1)校验和(段内部):和UDP的做法一样,也要伪首部,和UDP不同的是这个功能在TCP中是必须的
 
(2)确认:ACK的确认机制(下面是一些原则)
  • ACK报文不需要确认,也不消耗序号
  • 当一端发送数据时,尽量包含捎带确认。
  • 收端推迟发送ACK报文段,如果仅有一个未确认的按序报文段;延迟到500ms,或者有第二个报文段接收时(下一条),或者有数据要发送时(下一条)
  • 任何时候,不能有两个(以上)未确认的报文段(就是说如果收端有两个未确认的按序报文段,就马上发送ACK报文段进行确认)
  • 当收到一个序号比期望序号还大的报文段时,马上发送ACK,让发端进行快重传
  • 收到重复的报文段,就立即发送确认(解决ACK丢失问题)
(3)确认类型
  • 累计确认:收端忽略掉所有失序报文,告知发端他期待下一个收到的序号,叫做肯定累计ACK。肯定是说:丢弃的,丢失的,重复的都不报告。(累积是什么意思?累积就是我连着发送了两个1024的数据包,收到一个(只一个)ACK确认包,序号为2049,则表示我发送的两个1024的数据都已收到了)
  • 选择确认(SACK):在某些新TCP实现里面实现了这个东西,报告失序和重复的数据,作伪TCP首部选项字段的一部分。
(4)重传(两种情况) : 重传定时器时间到 或者 发端收到重复的三个ACK(快重传)
 
 
5.TCP三种计时器
 
A:重传计时器  为了控制丢失的或丢弃的数据段,TCP采用重传记时器来保障的
当发送方发送一个数据后,就立即启用重传记时器。1:如果在记时器截止时间前收到了确认,就撤消。  2:如果没有收到就重新发送数据。同时也起用记时器。
 
B:坚持计时器:为了对付零窗口,假如接受端宣布窗口关闭了,发送端则停止发送数据了,直到接收端从新开始打开并发送一个确认。 但这个确认有可能丢弃。这样就会造成发送端在“死等待”。双方进入死锁状态。为了防止这种现象的发生,发送端就起用了坚持记时器,等记时器到期限时,就会主动的发送探测包文。
 
C:保活计时器  保活记时器是用来防止在两个tcp之间的连接长时间空闲。假如客户打开服务器的连接就传了一部分数据。然后就不传输了,不管客户是什么原因,这个连接还是打开的。如果永远这样,就浪费资源了。为解决这个问题,我们使用了保活记时器。如果超过两个小时了,还没有信息传输,则会发探测数据段,连续发10个(每个隔75s) 假如还是没有,就关闭
 
 
6.TCP关闭状态转移
 
 
 
几个重要的状态:
 
FIN_WAIT_2:
上面已经详细解释了这种状态,实际上FIN_WAIT_2状态下的SOCKET,表示半连接,也即有一方要求close连接,但另外还告诉对方,我暂时还有点数据需要传送给你(如图中的服务器),稍后再关闭连接。
 
CLOSE_WAIT: 
这种状态的含义其实是表示在等待关闭。怎么理解呢?当对方close一个SOCKET后发送FIN报文给自己,你系统毫无疑问地会回应一个ACK报文给对方,此时则进入到CLOSE_WAIT状态。接下来呢,实际上你真正需要考虑的事情是察看你是否还有数据发送给对方,如果没有的话,那么你也就可以close这个SOCKET,发送FIN报文给对方,也即关闭连接。所以你在CLOSE_WAIT状态下,需要完成的事情是等待你去关闭连接
 
TIME_WAIT
保证发送端的最后一个ACK可以被正确的接收到
 
RST:(Reset the connection)用于复位因某种原因引起出现的错误连接,也用来拒绝非法数据和请求。会直接关闭连接
 
五、应用层
 
常见的基于TCP协议的应用有:HTTP、SMTP、Telnet、FTP等
常见的基于UDP协议的应用有:DNS、SNMP等
 
具体的如下图所示: