TCP(二)

在阐述TCP连接建立和终止的原理时,课本使用了Telnetdiacard服务。这里对Telnet作一个简短回顾。


Telnet协议允许用户通过网络登录远程的计算机系统。这里所指的计算机系统不仅仅是基于Unix的,只要支持Telnet协议的系统都可登录。登录通常需要账号,但有些远程主机允许无账号登录。连接一经建立,你在终端的任何按键都将传递给远程主机。Telnet服务的Well-known端口号是23

telnet命令:
telnet [options] [host [port]]
host
可以是主机域名或者是IP地址
常用的两个选项 -a 尝试自动登录
              
-l
指定登录用户

telnet客户端有两种操作模式:输入模式(input mode)命令模式(command mode)。不带参数直接执行telnet,终端显示telnet>提示符,这就是命令模式。在与服务器建立连接之后就进入输入模式。除了^],其他任何输入模式数据都将通过服务器telnet进程传输给服务器用作执行命令。^]telnetescape字符:从输入模式退出到命令模式(使用Ctrl+]按键)

几个telnet命令(在命令模式下输入):
?或help 显示telnet命令列表
close
quit 关闭telnet连接
z
挂起telnet会话,返回本地主机,用fg重启telnet


tcpdump输出简介

    tcpdump是网络数据采集分析工具。对tcpdump输出的简单介绍。

09:33:11.723111 IP 192.168.1.100.43136 > 210.32.0.10.telnet: S 470329474:470329474(0) win 5840 <mss 1460,sackOK,timestamp 1366083 0,nop,wscale 2>

09:33:11.723111  
时间,精确到1微秒
IP 192.168.1.100.43136 > 210.32.0.10.telnet:S  
源IP.端口号>目标IP.端口号:标志
在单个报文段中,标志可能不止一个,但通常我们每次只看到一个.
470329474:470329474(0)  
顺序号:隐含的结尾顺序号(数据长度)。其中隐含的结尾顺序号出现在两种情况下:
1TCP报文段中包含一个或者多个字节的数据;
2SYN,FINRST至少有一个打开
win 5840  
窗口大小5840字节(注若每次都要显示绝对数序号,需要在tcpdump后加参数-S,否则后续的显示相对顺序号)
mss 1460  
最大报文段长度 1460字节 ,由发送者指定。这样规定通常是为了避免分段.
(后面字段再补充)


TCP连接的建立

建立TCP连接的步骤:
    1.
请求端(通常称为client)发出一个SYN segment,该segment中指明了它希望连接服务器的端口号,以及它自己的ISN
    2.
server用它自己的SYN段响应客户端请求,其中包含了server的ISN。同时,server用client的ISN+1确认收到client 的 SYN
    3.
client用server 的 ISN+1确认收到server的SYN
这通常称为三步握手(three-way handshake)。

    我们说发出第一个SYN的那端执行主动打开(active open),而接收这个SYN,发出另一个SYN的那端执行被动打开(passive open)

       当每一端发送它的SYN来建立连接的时候,他都给连接选择了一个初始顺序号ISN。ISN随时间变化,因此每个连接有不同的ISN。RFC793指出,ISN应该看作一个32位的计数器,并且每4微秒递增1。顺序号用来防止网络上延迟的数据包被当前连接误用。


TCP连接终止

    由于TCP提供全双工的服务,每个方向的数据流独立传输,因此需要对每个方向的传输进行单独关闭,这通常引起所谓的TCP半关闭(half-close)。原则是每一端在发送完数据后向另一端发出FIN。当TCP收到一个FIN后,它就通知应用程序这个方向的数据流已经结束。图

zzz

连接通常由client发起。但两端都可以主动关闭(active close)它,一般是由client来决定中止连接,因为它受用户交互。
    与前文类似,称发出第一个FIN的那端执行主动关闭(active close),而另一端执行被动关闭(passive close)。和SYN一样,FIN也消费一个顺序号.


连接建立的超时(Timeout of  Connection Establishment )

     有一些情况下,连接可能无法建立,比如telnet一个处于非正常状态的server。看课本提供的一个例子:在断开server的以太网电缆之后,telnet该server。下图是连接超时的tcpdump输出



    这里重要的一点是:client TCP向server 发SYN,试图建立连接的频率怎么确定。前两次间隔5.8秒,第3和第2间隔了24秒。许多Berkeley派生的系统把建立一个新连接的时间限制在75秒。

    上图中一个疑惑的问题是首次超时时间,5.8秒,接近6秒。而且超过10次的试验显示该值在5.59秒到5.93秒之间。BSD在实现TCP时,使用了一个定时器,它每500毫秒超时一次。当我们键入telnet命令时,建立了一个初始值为6秒的定时器(对于500毫秒的定时器来说就是12个时钟tick),但它可能在将来的5.5到6秒之间触发(expire)。尽管定时器初始为12个tick,但计时器的第一次递减(减1)发生在它设置后的0-500毫秒之间。从这第一个递减点起,每过 大约500毫秒(大约?保不准那时正好有中断到来),定时器就减一。

    服务类型域(TOS)。上图中出现了[tos 0x10],这是IP数据报中的服务类型域。(这里是设置最小延迟)
最大segment长度(MSS)
    最大segment长度(MSS)TCP可以发送给对方的最大数据块chunk of data(MTU,
Maximum Transmission Unit,最大传输单元,是指在物理网络中可以传输的最大IP数据报大小,比如,以太网MTU为1500字节

    在连接建立时,每一端通告它期望的MSS。当TCP发送SYN时,它可以发送一个MSS值(最大值可以设置为外层接口的MTU - 20字节的TCP头域 - 20字节的IP头域)。如果一端没有收到另一端的MSS通告,那么数据块大小将默认为536字节,IP数据报就是576字节(加20字节的IP头域和20字节的TCP头域)。使用IEEE802.3封装,MSS最大可达到1452字节。许多BSD实现中,MSS值是512的倍数。
   
    一般的,MSS越大越好,但要考虑分段(fragmentation)的因素。MSS该越大意味着报文中数据所占比重越大,效率越高。如果目标IP地址是非本地的(两端的网络号不同),MSS通常默认为536,为避免分段,连接双方往往不发送超过较小MSS的数据块。但如果中间网络的MSS小于连接两端较小的MSS,比如两端MSS都是536,而中间网络的MSS是296,就将会发生分段,具体后续学习。

TCP半关闭 (TCP half-close)

半关闭状态:连接一端停止了输出,但仍可以从另一端接收数据。下图是半关闭的一个例子  


    client向server发送FIN,表示其不再向server发送数据,但还可以接收server发过来的数据。如果server再无数据发给client,便发送FIN,client对此返回一个应答,至此,连接完全关闭。

    socket API shutdown支持半关闭,close全关闭。


TCP 状态迁移图

图中状态的命名和netstat命令的输出保持一致。CLOSED实际上不是一个状态,这里假想它是状态的起点和终点。在ESTABLISHED状态,双方已经建立了连接,可以双向地进行数据传输。

如果状态SYN_RCVD是从LISTEN迁移过来的,那么它在收到RST(重置连接)后可以从SYN_RCVD返回到LISTEN;如果是从SYN_SENT迁移过来的,则不可再迁移到LISTEN状态。也就是说,我们执行被动打开(进入LISTEN状态),接收到一个SYN,并发送对它的ACK和另一个SYN,即进入SYN_RCVD状态。这时如果收到ACK,将进入ESTABLISHED状态;但要是收到RST,则又回到LISTEN状态,等待新的连接请求的到来。

TIME_WAIT状态也称为2MSL等待状态。在TCP实现中,必须给报文段最大生存时间maximum segment lifetime ,MSL)指定一个值。这是TCP段在网络中存在而不被丢弃的最大时间量。但由于TCP段是封装在IP数据报中的,因此MSL又受TTLIP数据报的存活时间)限制。在实际中TTL是基于跳(hop)的数目,而非计时器。

给MSL设置值的原则TCP执行一个主动关闭,当它发送最后一个ACK后,连接必须在TIME_WAIT状态停留2MSL时间。这是为了在最后一个ACK丢失的情况下对其重发。2MSL等待的另一个影响是:在此连接中定义的socket对不能被重用,重用只能在2MSL状态结束以后。具体实例见课本P243-245

当连接处于2MSL状态时,它的任何延迟的TCP段都将被丢弃。连接由socket对来定义,我们称一个连接的新的实例(instance)为该连接的一个化身(incarnation)。由于在2MSL状态时定义一个连接的socket对不能被重用,因此该连接前一个化身的TCP段是不会被后一个化身曲解(misinterprete)(即误用)的。

通常是客户端执行主动关闭,进入TIME_WAIT状态,服务器执行被动关闭,不会进入TIME_WAIT状态。言下之意就是说,如果我们终止一个客户端,并立即重启一个相同客户端,那么新的客户端将不能使用相同的本地端口号。但这不成问题,因为客户端使用短暂的(ephemeral)端口,我们并不关心使用的本地端口号是多少。

但这对于服务器来说就不同了,因为服务器使用well-known端口号,比如telnet23。如果我们终止一台已经建立连接的服务器,并立即重启,那么服务器将不能立即使用它的well-known端口号,因为这个端口号还是处在2MSL状态的连接的一部分。

考虑一种情况:主机有端口号处于2MSL状态,但它却在MSL时间内崩溃并重启,而且重启后使用崩溃前处于2MSL状态的端口号建立了新的连接,此时主机崩溃前连接的延迟TCP段就会被当前新的连接误用。为避免这种情况发生,RFC793规定在重启后的MSL时间内不应该建立新的连接,这称为quiet time

只有当另一端的应用程序执行close,主动关闭端才能从FIN_WAIT_2状态迁移到TIME_WAIT状态,否则将永远等待下去。


复位报文段(reset segment)

    一般来说,当一个到达的TCP报文段对于某个指定连接(referenced connection)不正确时,就需要发出一个复位报文段reset segment)(所谓“指定连接”是指由某个socket对表示的连接)。

发出复位报文段的一个通常情况是:有连接请求到达,但却没有进程正在目标端口监听。在使用UDP的情况下,当一个数据报到达一个不在使用的端口号时,就产生一个端口不可到达的ICMP。但TCP使用复位:server向client发送一个RST报文,client重新进入LISTEN状态。

比如telnet远程主机时指定一个不在使用的端口号,远程主机将发回一个复位报文段。看课本上列出的两个包:

0.0 bsdi.1087 > svr4.20000: S 297416193:297416193(0) win 4096 <mss 1024> [tos 0x10]
0.003771 (0.0038) svr4.20000 > bsdi.1087: R 0:0(0) ack 297416194 win 0

由于svr4收到的TCP报文段没有打开ACK,因此复位段的顺序号是0。尽管收到的TCP段不带实际数据,但由于SYN位在逻辑上占用了顺序号空间的一个字节,所以本例中重置段的应答号是ISN+数据长度(为0+1,即297416194  

TCP连接的正常终止的情况:一端在所有排队数据发出后才发送一个FIN来终止连接,这也叫做有序释放(orderly release)。但有的时候可能用一个RST代替FIN来异常终止(abort)某个连接,有时也称之为异常释放(abortive release)

异常释放带给了应用程序两个特征:1)任何在排队的数据都被丢弃(throw away,并立即发出复位报文段;2)复位报文段的接受者能够区分对方是异常,而非正常关闭。应用程序使用的API必须提供产生异常而非正常关闭的方法。示例见P247-248

TCP连接的半打开(half-open)状态:一端已经关闭或者异常终止,却没有把这些通知给另一端。任何一端的主机崩溃(crash)都可能产生半打开状态。只要不打算在半打开的TCP连接上传输数据,仍处于连接状态的那一端就不会去检查另一端已经崩溃。

一种通常情况是连接的client掉电(power off),而server却不知道这个client已经消失。当client重启时将新建与server连接,这样就导致了server上很多的半打开TCP连接。

实践示例见P249


两端的应用程序同时向对方执行主动打开的情况是可能的,尽管发生的概率很小,这称为同时打开(simultaneous open)

TCP对同时打开进行了针对性的设计,遵守的原则是同时打开只建立一个连接,而非两个。

图:同时打开时的TCP段交换

同样地,连接两端同时执行主动关闭的情况称为同时关闭(simultaneous close)同时关闭时TCP段交换的图见下:

TCP 选项和TCP服务器设计(略)。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值