参考:http://blog.csdn.net/macdroid/article/details/49070185

在学习TCP之前我们先来看一下可靠数据传输需要提供什么样的机制:

·差错检测机制:检测数据包是否出现比特差错

·反馈机制:接收端对接收到的数据包的反馈

·序列号机制:解决冗余数据包问题

·定时器机制:解决丢包问题

·重传机制:解决数据包出错或丢失问题

下面就来介绍一个典型的可靠数据传输TCP:

TCP具有以下特点:

·点到点:
从一个发送方到一个接收方。连接状态与端系统有关,不为路由器所知。

·可靠、有序的字节流:
传输的数据没有“报文边界”

·流水线型的协议:
TCP拥塞和流量控制设置滑动窗口协议

·具有发送和接收缓冲区

·全双工数据:
同一连接上的允许双向数据流(MSS: 最大报文段长度,MTU:最大传输单元)

·面向连接:
在进行数据交换前,初始化发送方与接收方状态,进行握手(交换控制信息)

·流量控制:
发送方不能淹没接收方

·拥塞控制:
抑止发送方速率来防止过分占用网络资源

下图是TCP报文段的结构

由此可看出TCP首部的长度最少为20字节,因为上表中的“选项”通常是没有的。

TCP的可靠传输机制主要靠以下几个方面:

1.报文确认

接收方对于正确接收到的来自发送方的报文段要给予确认返回报文。该报文中的首部ACK指向接收方期待下一个开始接收的字节。

2.超时重传

当发送方发送报文之后,会启动一个倒数计时器(重传超时间隔),计时器为零时,就认为报文可能在网络中丢失,需要重传报文。

那么这个重传超时间隔的值要设为多少呢?

首先,这个值必须大于TCP连接的往返时延(RTT)。

TCP采用的是自适应的方法。设SampleRTT为样本RTT,就是从某报文被发出(即交给IP)到对该报文段的确认被收到之间的时间量。
在任意时刻只为一个已发送但未被确认的报文段估测量,并且仅为传输一次的报文段测量SampleRTT。
可是SampleRTT的值会因为网络的拥塞情况而不段的变化,所以需要一个均值EstimatedRTT:

SampleRTT = (1-a) * EstimatedRTT + a * SampleRTTs

RFC 2988中给出a参考值是0.125。从统计学观点来说,这种平均被称为指数加权移动平均

另外,测量RTT的变化也是有意义的。所以RFC 2988定义了RTT偏差DevRTT。

DevRTT = (1-b) * DevRTT + b * |SampleRTT - EstimatedRTT|

超时间隔应该是等于大于均值的,而超过的均值的范围值可以利用DevRTT。所以超时间间隔的公式就为:

TimeoutInterval = EstimatedRTT + 4 * DevRTT

3.快速重传

当发送端收到3个冗余ACK时就立即重传,而不必要等到定时器超时。

4.差错恢复

在了解TCP的差错恢复机制之前先要介绍下面两种协议:

·回退N步(GBN协议)

·选择重传(SR协议)

GBN(也叫滑动窗口协议):

send_base是基序号,指示最早的未确认分组的序号。 nextseqnum是下一个序号,指示最小的下一个待发送分组的序号。window size就是窗口大小。

每当收到ACK时,send_base指针就会变化,整个窗口就会前移。收到一个ACK时仍有未被确认分组,则计时器被重新启动。
如果出现超时,发送方将重传所有已发送但未确认的分组。
在GBN协议中,接收方会丢弃所有失序的分组。即使前面在失序分组前已经有好几个分组正确到达了。

回退N步示例:

SR:

一个单分组的差错或失序就可能引起GBN重传大量分组,许多分组根本没有必要重传。所以,选择重传协议通过让发送方仅重传它怀疑在接收方出错(即丢失或受损)的分组而避免来不必要的重传。

SR协议中:
发送方的中的每个分组必须拥有自己的逻辑定时器,因为超时后只能发送一个分组。可以使用单个硬件定时器模拟多个逻辑定时器的操作。
接收方将确认一个正确接收的分组而不管其是否按序。失序的分组将被缓存,直到一批分组按序接收成功了则交付上层。

由于接收方接收了分组就发送ACK,移动自身的接收窗口,而发送方有可能因为ACK丢失等原因迟迟没收到确认报文以至于窗口不移动。所以,对于SR协议而言,这就意味着发送方和接收方的窗口并不总是一致。

选择重传示例:

TCP的差错恢复机制为选择确认。

它允许TCP接收方有选择地确认失序报文段,而不是累积地确认最后一个正确接收的有序报文段。当将该机制与选择重传机制结合起来使用(即跳过那些已被接收方选择性地确认过的报文段的重传)时,TCP看起来像我们通常的SR协议。因此TCP的差错恢复机制可以被划分为GBN协议与选择重传协议的混合体

下面来详细解释一下TCP的有限状态机

TCP_CLOSE:关闭状态,一个新建的TCP socket会处于该状态。

TCP_LISTEN:监听状态,一般服务器端套接字在调用Listen系统调用后即处于该状态。

TCP_SYN_SENT:同步信号已经发送状态,这个状态一般是指客户端发送SYN(建立连接的同步)数据包后所处的状态(tcp三次握手的第一个包)。在接收到远端服务器端的应答后,即从该状态进入TCP_ESTABLISHED状态。

TCP_SYN_RECEIVED:同步信号已经接受状态,服务器端在接受到远端客户端SYN数据包后,进行相应的处理(创建通信套接字等),然后发送应答数据包(tcp三次握手的第二个包),并将新创建的通信套接字状态设置为TCP_SYN_RECEIVED,在接受到客户端的应答后,即进入TCP_ESTABLISED状态。

TCP_ESTABLISED:建立连接状态,这是双方进行正常通信所处的状态。

TCP_FIN_WAIT_1:本地发送FIN(用于结束连接的)数据包后即可进入该状态,等待对方的应答。一般一端发送完其所要发送的数据后,即可发送FIN数据包,此时发送通道被关闭,但仍可继续接受远端发送的数据包。在接受到远端发送的对于FIN数据包的应答后,将进入TCP_FIN_WAIT_2状态。

TCP_FIN_WAIT_2:进入该状态表示本地已经接收到远端发送的对于本地之前发送的FIN数据包的应答。进入该状态后,本地仍然可以继续接收远端发送给本地的的数据包。在接收到远端发送的FIN数据包后(表示远端也已经发送完数据),本地将发送一个应答数据包,并进入TCP_TIME_WAIT状态。TCP_TIME_WAIT状态存在的时间被称为2MSL时间,这一方面是为避免本地发送的应答数据包丢失,另一方面避免一个新创建的套接字接收到旧套接字中遗留的数据包。

TCP_TIME_WAIT:该状态被称为2MSL等待状态。如果在此期间接收到远端发送的FIN数据包,则表示之前在TCP_FIN_WAIT_2状态发送的ACK应答数据包在传输中丢失或者长时间被延迟,从而造成了远端重新发送了FIN数据包,此时重复ACK应答数据包。一旦2MSL时间到期,则将进入TCP_CLOSED状态,即完成关闭操作。

TCP_CLOSE_WAIT:该状态存在于后关闭的一端。当接收到远端发送的FIN数据包后,本地发送一个ACK应答数据包,并将该套接字状态从TCP_ESTABLISED设置为TCP_CLOSE_WAIT。本地可以继续向远端发送数据包,在发送完所有的数据后,本地将发送一个FIN数据包关闭本地发送通道,并将状态设置为TCP_LAST_ACK状态,等待远端对FIN数据包的应答数据包。

TCP_CLOSING:如果通信双方同时发送FIN数据包,则同时进行关闭操作,则双方将同时进入TCP_CLOSING状态。具体的,本地发送一个FIN数据包以结束本地数据包发送,如果在等待应答期间,接收到远端发送的FIN数据包,则本地将状态设置为TCP_CLOSING状态。在接收到应答后,再继续装入到TCP_CLOSE_WAIT状态。

TCP_LAST_ACK:作为后关闭的一方,在发送FIN数据包后,即进入TCP_LAST_ACK状态。此时等待远端发送应答数据包,在接收到应答数据包后,即完成关闭操作,进入TCP_CLOSE状态。

下面是上述过程的更直观的体现:

TCP三次握手:

步骤:
1.客户端向服务端发送一个特殊的TCP报文段。该报文段不包含应用层数据,但需要把报文段首部的SYN标志位置1。这个报文被称为SYN报文段。除了SYN,还需要加上SEQ字段指示客户端的开始序号。
2.服务端接收到SYN报文之后,就为该TCP连接分配TCP缓存和变量,并向客户端发送允许连接的报文段。该报文段包含SYN和SEQ,意义同上。但还附带一个ACK指示想要收到的下一个字节。该允许连接的报文段有时被称为SYN_ACK报文段。
3.在收到来SYN_ACK报文段后,客户机也要给该连接分配缓存和变量。这时客户端还会向服务端发送另一个报文段,是对SYN_ACK报文段进行确认。因为连接已经成功建立,所以该SYN被置0。

TCP四次挥手:

步骤:
如图所示,客户端应用进程发出一个关闭连接命令。这会引起客户端TCP向服务端进程发送一个特殊的TCP报文段。这个特殊的报文段首部中的FIN比特被置1。当服务接收到该报文段后,就向客户端会送一个确认报文段。这时,TCP连接处于半关闭状态。半关闭指的是客户端已经不能再给服务端发送数据了,但可以接收服务端发过来的数据。数据传送完毕之后,服务端发送其终止报文段,同样FIN被置1。最后客户端对这个服务端的终止报文段进行确认。两台主机的TCP连接成功释放。
注意,如果服务端不需要向客户端传输数据了,那么ack = u + 1的这个两个报文是可以结合为一个的。

【问题1】为什么客户端最后需要等待2MSL呢?

MSL意思是报文段最大生存时间(Maximum Segment Lifetime)。它是任何报文段被丢弃前在网络内的最长时间。因为网络层有限制生存时间字段TTL,所以MSL值是有限的,常用可能会30秒,1分钟,2分钟。

TIME_WAIT确保有足够的时间让对端收到了ACK,如果被动关闭的那方没有收到Ack,就会触发被动端重发Fin,一来一去正好2个MSL

【问题2】如果因为机器故障而导致连接被中断要怎么办?

TCP设有一个保活计时器。服务端每收到一次客户的数据都会重新设置该计时器。计时器到时之后,服务端会主动发送探测报文,连续几个探测报文没反应的话,服务端就会自动关闭。

【问题3】为什么连接的时候是三次握手,关闭的时候却是四次握手?

因为当服务端收到客户端的SYN连接请求报文后,可以直接发送SYN_ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当服务端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉客户端,"你发的FIN报文我收到了"。只有等到我服务端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手。

[计算机网络-传输层] 面向连接的传输:TCP的更多相关文章

  1. Android程序员必知必会的网络通信传输层协议——UDP和TCP

    1.点评 互联网发展至今已经高度发达,而对于互联网应用(尤其即时通讯技术这一块)的开发者来说,网络编程是基础中的基础,只有更好地理解相关基础知识,对于应用层的开发才能做到游刃有余. 对于Android ...

  2. java 网络通信传输层协议——UDP和TCP

    本文原文由作者“zskingking”发表于:jianshu.com/p/271b1c57bb0b,本次收录有改动. 1.点评 互联网发展至今已经高度发达,而对于互联网应用(尤其即时通讯网专注的即时通 ...

  3. [19/04/13-星期六] 网络编程_基本概念(关注传输层、数据传输,TCP和UDP)

    一.概念 ▪ 什么是计算机网络? 计算机网络是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统, 网络管理软件及网络通信协议的管理和协调下,实现资源共享和信 ...

  4. 计算机网络-传输层(3)TCP协议与拥堵控制

    TCP是因特网传输层的面向连接的可靠的运输协议.   TCP被称为是面向连接的:通信双方在发送数据之前必须建立连接,连接状态只在连接的两端中维护,在沿途节点中并不维护状态. TCP连接包括:两台主机上 ...

  5. 传输层中的协议 TCP & UDP

    面向连接的TCP协议 “面向连接”就是在正式通信前必须要与对方建立起连接.比如你给别人打电话,必须等线路接通了.对方拿起话筒才能相互通话.TCP(Transmission Control Protoc ...

  6. 网络协议学习笔记(四)传输层的UDP和TCP

    概述 传输层里比较重要的两个协议,一个是 TCP,一个是 UDP.对于不从事底层开发的人员来讲,或者对于开发应用的人来讲,最常用的就是这两个协议.由于面试的时候,这两个协议经常会被放在一起问,因而我在 ...

  7. 传输层(一)TCP的三次握手和四次挥手及关闭套接字的原理

    TCP连接需三次握手才能建立,断开连接则需要四次握手. 客户端TCP状态迁移: CLOSED->SYN_SENT->ESTABLISHED->FIN_WAIT_1->FIN_W ...

  8. 传输层的端口与TCP标志中的URG和PSH位

    一.协议端口号的提出 运输层提供了进程间通信的能力(即端-端通信).但是不同的操作系统可能无法识别其他机器上的进程.为了用统一的方法对 TCP/IP体系的应用进程进行标志,使运行不同操作系统的计算机的 ...

  9. 传输层(2)-TCP连接的建立和终止、TIME_WAIT状态

    1.TCP连接的建立和终止 1)三路握手 客户端发送一个SYN(同步)分解,告诉服务器客户将在连接中发送的数据的初始序列号. 服务器发送确认客户的SYN(ACK),同时自己也得发送一个SYN分节,它含 ...

随机推荐

  1. Qt udp 主机和虚拟机无法互相广播

    描述: 主机和虚拟机可以ping通,port没被占用,虚拟机可以向主机广播,但是主机不能向虚拟机广播 原因: 虚拟机只配置了一个适配器,而主机有多个适配器,当虚拟机广播时,只能使用和主机连接的适配器, ...

  2. 常用数字信号的产生(C实现)-均匀分布&正态分布

    小白博主开始学DSP之路,为了激励自己能坚持下去,写一系列博客来记录下来,也欢迎与大家一起讨论.介于我能力所限,这里学习目标定为,学习一个基础知识,写一个C语言程序实现, 最后会形成一个C的函数库,方 ...

  3. 【EXCEL】XMLファイルを開く方法(XML文件打开方法)

    前言 XMLとは:Extensible Markup Language(エクステンシブル マークアップ ランゲージ)は.基本的な構文規則を共通とすることで.任意の用途向けの言語に拡張することを容易とし ...

  4. shell基础笔记

    什么是shell脚本 我自己对shell脚本的理解就是一系列的shell命令加入逻辑关系,实现类似"批处理"的功能.而不是简单的命令的堆砌,那样的shell脚本bug重重. 脚本开 ...

  5. 20145202马超《java》【课堂实验】P98测试

    当时在加水印所以没来得及提交,然而我回宿舍第一时间就提交了,希望老师额能够看到

  6. BZOJ2330_糖果_KEY

    题目传送门 看题目可知这是一道差分约束的题目. 根据每种关系建边如下: 对于每种情况建边,然后跑一边SPFA.(最长路) 因为可能会有自环或环的情况,都不可能存在. 跑SPFA时记录入队次数,超过N弹 ...

  7. Netty示例

    一,服务端 ** * 测试Netty类库:服务端代码 * Created by LiuHuiChao on 2016/10/24. */ public class NettyServerTest { ...

  8. (转) 如何从 0 开始学 ruby on rails (漫步版)

    原文:http://readful.com/post/12322300571/0-ruby-on-rails ruby 是一门编程语言,ruby on rails 是 ruby 的一个 web 框架, ...

  9. elasticsearch安装中文分词器

    1. 分词器的安装 ./bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/rele ...

  10. Hadoop3.0新特性

    1. Hadoop3.0简介 Hadoop 2.0是基于JDK 1.7开发的,而JDK 1.7在2015年4月已停止更新,这直接迫使Hadoop社区基于JDK1.8重新发布一个新的Hadoop版本,而 ...