热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

TCP/IP详解TCP连接与终止(18)

建立连接: 三次握手的过程: 报文段1:请求端发送一个SYN段指明客户端打算连接的服务器的端口, 以及初始化序号。【ISN, 在这里是1415531521】 报文
TCP/IP详解 TCP连接与终止(18)

TCP/IP详解 TCP连接与终止(18)

建立连接:

三次握手的过程:

  1. 报文段1:请求端发送一个SYN段指明客户端打算连接的服务器的端口, 以及初始化序号。【ISN, 在这里是1415531521】
  2. 报文段2:服务器发挥包含服务器的初始序号的SYN报文段作为应答; 同时,将确认序号设置为客户端的ISN 加1以对客户的SYN报文段进行确认。 一个SYN将占用一个序号。
  3. 报文段3:客户必须将确认序号设置为服务器的ISN+1以对服务器的SYN报文段进行确认。

建立协议的状态变化:

  1. 发送第一个SYN的一端将执行主动打开(active open)。 接收这个SYN并且发挥下一个SYN的另一端执行被动打开(passive open)。
  2. 当一端为了建立连接而发送它的SYN时, 它为了连接选择一个初始化序号。 ISN随时间而变化,因此每个连接都将具有不同的ISN。 (ISN可看做是一个32bit的计时器,每4ms 加1), 这样的选择序号的目的在于防止在网络中被延迟的分组在以后又被传送,而导致某个连接的一方对它作错误的解释。

    TCP/IP详解 TCP连接与终止(18)
    防止上一个连接断开了,但是数据还是在网络上游荡,但是我们新的连接建立之后,是否要接收到这个连接的问题
  3. 序号的选择:4.4BSD中,系统初始化时初始的发送序号被初始化为1。这个变量每0.5S增加64000, 并每隔9.5小时又回到0(对应每个计数器每8ms加1,而不是每4ms加1),另外,每次建立一个连接后, 这个变量加增加64000 ——这种方法违背了Host Requirements RFC

???
这里有个疑问? 为什么我我们需要三次握手?? 两次不可以么? 我准备发送数据给你, 收端,开启进程等准备工作, 然后就是返回一个ack, 发端就发送数据了,这样不可以么? 发端收到ack说明服务器已经进行了响应的准备,但是, 收端,怎么知道发端已经收到我的信息了呢?发端再发一个ack,表示已经收到,然后开始发送信息, 如果收端没有收到发端的ack这个报文? 三次也是不可靠的???
三次握手的问题
三次握手连接、四次握手断开

需要注意的是:我们会将充电放在: 为什么需要TCP建立连接需要三次握手? 而不仅仅是为什么需要三次握手?
可靠性以及控制流量: 序列号(两端的syn序列号)【重排等】,socket、流量控制【流量控制应该是比较容易的,序列号都同步了,window size 应该是更加容易的替换更新了】

连接终止:
《四次握手》

TCP/IP详解 TCP连接与终止(18)
四次握手
  1. 由于TCP的半关闭(half-close)造成的。 既然一个TCP链接是全双工【两个方向上能够同时传递】,因此每个方向必须单独地进行关闭。 这个原则就是当一方完成它的数据发送任务就能够发送一个FIN, 它必须通知应用层另一端已经终止嘞 那个方向的数据传送。 发送FIN通常是应用层进行关闭的结果。
  2. 收到一个 FIN只意味着在这一方向上没有数据流动。一个TCP连接在收到一个FIN后,仍能够发送数据。 而这对利用半关闭的应用来说是可能的, 尽管在实际应用中只有很少的TCP应用程序这样做。
  3. 首先进行关闭的一方(即为发送第一个FIN)将执行主动关闭,而另一方(收到这个FIN)执行被动关闭。通常一方完成主动关闭而另一方完成被动关闭。
  4. 发送FIN将导致应用程序关闭它们的连接, 这些FIN的ACK是由TCP软甲自动产生的。

连接建立的超时
—— 对第一个SYN的重发机制

TCP/IP详解 TCP连接与终止(18)
使用telent的一个例子
  1. 发现: 第2个SYN与第1个的间隔时间是5.8s, 而第3个与第2个的时间间隔是24s。 【增额例子大概是38分钟重新启动的,对应的初始序号为291008001 ,(大约是38 * 60 64002),这个是BSD系统初始化为1,没0.5s就增加6400; 由于系统启动后的一个TCP连接,端口号是1024】
    ??? 这个发现了一个问题,第一个时间间隔接近6s,但是不准确。

    TCP/IP详解 TCP连接与终止(18)

    由于BSD是采用500ms的定时器用于确定本章中的所有各种各样的TCP超时,我们输入命令的时候,将建立一个6s的定时器(12个时钟)尽管初始化是12个时钟滴答,但是在0500ms中的任意时刻减1.所以,一个时间间隔是5.5s6s之间的任意时刻。【因为第一个500ms内是可变的, 因为在TCP每隔500ms获得系统控制的瞬间, 系统内核可能会优先处理其他中断】

2)

TCP/IP详解 TCP连接与终止(18)
记录重传的倒计时

时间差值是76s, 大多数BSD系统建立一个新连接最长的时间是75s。 我们可以在21.4看到是 16: 25:29超时, 可以看到第三个分组发出48s后放弃而不是72秒【这个在后面再进行一次理解这个内容】;


最大报文段长度 MSS “协商”的选项

  1. 它并不是任何条件下都可协商的。 当建立一个连接时, 每一方都用于通告它期望接收的MSS选项。【MSS选项只能够出现在SYN报文段中】; 如果一方不接收来自另一方的MSS的值,则MSS就定位默认值536字节。
  2. 一般情况下,没有分段的时候,MSS越大越好【这个不一定正确】;因为MSS值越大的时候,报文段越大允许每个报文传送的数据就越多, 相对IP和TCP首部有更高的网络利用率。 当TCP发送一个SYN时,或者是因为一个本地应用进程想发起一个连接,或者是因为另一端的主机收到一个连接请求,它能将MSS值设置为外出接口上的MTU长度减去固定的IP首部和TCP首部长度。对于一个以太网,MSS值可达1460字节。
  3. 如果目的IP地址为“非本地的(nonlocal)”,MSS通常默认值是536.
    【区分地址是本地还是非本地的简单, 如果目的IP地址的网络与自网络号都和我们相同,则是本地的,如果IP地址的网络号和我们完全不同,非本地,如果ip地址的网络号和我们相同而子网络号,这个是由网路管理员来进行更进行设置的选项】

TCP 的半关闭
TCP 提供了连接的一端在结束它的发送后还能够接收来自另一端数据的能力 —— 半关闭

TCP/IP详解 TCP连接与终止(18)

TCP/IP详解 TCP连接与终止(18)
一端要求另一端排序的交互

左端发起了排序的请求, 然后左端发起了fin结束传输数据的请求, 右边进行了排序,-然后传输回来一些结果, 再发起终止请求


《TCP的状态变迁图》

TCP/IP详解 TCP连接与终止(18)

TCP/IP详解 TCP连接与终止(18)

2MSL 是Time wait 状态等2msl之后再发送的,还是发送之后2msl就销毁了这个状态?

MTU /MSS / MSL
MTU 和MSS区别
RTT 往返时间 (Time To Time)
MSL 报文最大的生存时间 (Maximum Segment Lifetime)
为什么TCP4次挥手时等待为2MSL??? 这个需要进一步去验证这个东西;
2MSL
MSL /RTT /TTL


2MSL等待状态 —— 这个过程还是不太理解。

  1. TIME_WAIT 状态也称为SMSL等待状态。每个具体的TCP实现必须选择一个报文段最大生存时间MSL。 它是任何报文段被丢弃前在网络内的最长时间。 [MSL实现中常用值是:30s, 1分钟、2分钟]【这个时间是有限的, 因为TCP报文段以IP数据报在网络内传输,而IPO数据报则有限制其生存时间的TTL字段】
  2. 对一个具体实现所给定的MSL的值,处理的原则是: 当TCP执行一个主动关闭,并发回最后一个ACK, 该连接必须在TIME_WAIT状态停留的时间为2倍的MSL。 这样可让TCP再次发送最后的ACK以防这个ACK丢失(另一端超时并重发最后的FIN)。【这个地方还是有点不太理解】
  3. 这种2MSL等待的另一个结果是这个TCP连接在2MSL等待期间,定义这个连接的插口(客户的IP地址和端口号,服务器的IP地址和端口号)不能再被使用。这个连接只能在2MSL结束后才能再被使用。
  4. 在连接处于2MSL等待时, 任何迟到的报文段将被丢弃。 因此处于2MSL等待的,由该插口对(socket pair) 定义的额连接在这段时间内不能被再用,因此当要简历一个有效的连接时,来自改连接的一个较早替身(incarnation)的迟到报文段作为新连接的一部分不可能被曲解。
  5. 客户端执行关闭并进入TIME_WAIT 是正常的, 服务器通常执行被动关闭, 不会进入TIME_WAIT 状态。 这暗示如果我们终止一个客户端程序,并立即重新启动这个客户程序,则新的程序不会使用统统的本地端口,这个不会带来问题,因为客户使用本地端口,而不关心这个端口是什么。
  6. 对于服务器,情况有所不同,因为服务器使用的是知名端口。 如果我们终止一个已经建立连接的服务器程序, 并试图立即重新启动这个服务器程序,服务器程序不能把它的这个知名端口赋值给它的端点, 因为这个端口处于2MSL连接的一部分。 在重新启动服务器程序前, 它需要在1~4分钟。 [也就是服务器启动会等待时间销毁完成了之后,才会重新开启,使用同样的知名端口]

这里的两倍报文段的时间长度 。。。。

平静时间 —— 这个概念一般没有什么用处

  1. 对于来自某个链接的焦躁跌的替身的迟到报文段,2MSL等待可防止将它解释成使用相同插口对的新连接的一部分。 但这只有在处于2MSL等待连接中的主机处于正常工作状态时才有效
  2. 如果使用处于2MSL等待短开口的主机出现故障, 它会在MSL秒内重新启动, 并立即使用故障前仍处于2MSL的插口对来简历一个新的连接吗?如果是这样,在故障前从这个连接发出而迟到的报文段会被错误地当做属于重启后新连接的报文段。无论如何选择重启后新连接的初始序号,都会发生这种情况。
  3. 为了防止这种情况, RFC 793 指出TCP在重启后的MSL秒内不能够简历任何连接 —— 平静时间
  4. 只有极少的实现版遵守这个原则,因为大多数主机重启的时间都比MSL秒要长。

FIN_WIAT_2 状态

  1. 在FIN_WAIT_2 状态我们已经发出了FIN, 并且另一端也已对它进行了确认。 除非我们在实行半关闭, 否则将等待另一端的应用层意识大搜它已收到一个文件结束符说明,并向我们发一个FIN来关闭另一方向的连接。 只有当另一端的京城完成这个关闭,我们这端才会从FIN_WAIT_2状态进入TIME_WAIT状态。
  2. 这意味着我们这端可能永远保持这个状态。 另一端也将处于CLOSE_WAIT状态, 并一直保持这个状态知道应用层决定进行关闭。

复位报文段

RST :复位标志, 无论合适一个报文段发往基准的连接[referenced connection]出现错误, TCP都会发出一个复位报文段。【基准连接:指由目的IP地址和目的端口以及源IP地址和源端口号指明的连接】

《1》 到不存在的端口的连接请求

产生复位的一种常见情况是当连接诶请求到达时, 目的端口没有进程正在听。
TCP使用了复位;
UDP: 当一个数据报到达时, 该端口没有时候用,它产生一个ICMP端口不可达的信息

《2》异常终止一个连接

  1. 终止一个连接的正常方式是一方发送FIN。 有时这也称为有序释放(orderly release)
  2. 有可能发送一个复位报文段而不是FIN来中途释放一个连接。 有时候称这为异常释放
  3. 异常终止一个连接对应用程序来说有两个优点: 丢弃任何待发数据并立即发送复位报文段 RST的接收方会区分另一端执行的是异常关闭还是正常关闭。 [ 应用程序使用的API必须提供产生异常关闭而不是正常关闭的手段。]

《3》检测半打开连接

前面提到的半关闭,那个是正常的关闭状态。

如果一方已经关闭或者异常终止而另一方确还不知道 —— TCP连接成为半打开(half-open)
【任何一端主机异常都可能导致发生这种情况。 只要不打算在半打开连接上传输数据,仍处于连接状态的一方就不会检测另一方已经出现异常 —— 半打开的状态,但是没有数据传输,这个时候就不管了

TCP/IP详解 TCP连接与终止(18)

同时打开【了解】

TCP/IP详解 TCP连接与终止(18)
同时打开

同时关闭【了解】

TCP/IP详解 TCP连接与终止(18)

TCP 选项

TCP/IP详解 TCP连接与终止(18)
TCP选项格式
  1. 每个选项的开始是1byte的kind字段,说明选项类型。kind =0、1 的选项仅占1个字节。其他的选项在kind字节后还有len字节。它说明的长度是指总长度, 包括kind字节和len字节。
  2. TCP/IP详解 TCP连接与终止(18)

TCP 的建立和关闭以及其中的各个时间段的状态


推荐阅读
author-avatar
慧慧2502916487
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有