2018-07-19

TCP知识点总结

TCP概述

a. TCP提供的是面向连接的全双工服务
TCP所有的数据会匹配到由源地址、目的地址、源端口、目的端口构成的一个TCP连接之上。TCP连接是一中需要建立的资源,可以握手机制来完成。UDP是一种基于尽力而为机制的协议,不存在UDP连接资源的建立,资源的处理往往由应用层协议代劳。

b. TCP可供可靠的服务
TCP有确认机制来保证数据包的可靠到达
TCP有CRC校验机制来保证数据包的无差错性,UDP的CRC是可选的
TCP会重新排序乱序的数据包和丢弃重复的数据
TCP能够提供流量控制机制,使用滑动窗口算法
TCP能够提供拥塞控制器与恢复机制,存在多种TCP拥塞控制模型
TCP能协商发送的数据报文长度

TCP报文格式

图片1.png

TCP报文段各个部分的格式如上图所示。下面解释一下各个字段的含义:

端口号
1)源端口:源端口和IP地址的作用是标识报文的返回地址。
2)目的端口:端口指明接收方计算机上的应用程序接口。
TCP报文中的源端口号和目的端口号同IP数据报中的源IP和目的IP唯一确定一条TCP连接

序号和确认号
序号和确认号是TCP可靠传输的关键部分。序号是本报文段发送的数据组的第一个字节的序号。在TCP传送的流中,每一个字节一个序号。例如,一个报文段的序号为300,此报文段数据部分共有100字节,则下一个报文段的序号为400。所以序号确保了TCP传输的有序性。确认号,即ACK,指明下一个期待收到的字节序号,表明该序号之前的所有数据已经正确无误的收到。确认号只有当ACK标志为1时才有效。比如建立连接时,SYN报文的ACK标志位为0。

数据偏移/首部长度
占用4bits,由于首部可能含有可选项内容,因此TCP报头的长度是不确定的,报头不包含任何选字段则长度为20字节,4位首部长度字段所能表示的最大值位1111,转化为10进制为15,15*4=60,故报头最大长度为60字节。首部长度也叫数据偏移,是因为首部长度实际上指示了数据区在报文段中的起始偏移值。

保留
为将来定义新的用途保留,现在一般置0。

控制位
URG、ACK、PSH、RST、SYN、FIN共6个,每一个标志位表示一个控制功能。
1)URG: 紧急指针标志,为1时表示确认号有效,为0则忽略紧急指针。
2)ACK: 确认序号标志,为1时表示确认号有效,为0时表示报文中不含确认信息,忽略确认号字段。
3)PSH: push标志,为1表示是带有push标志的数据,指示接收方在接收到该报文段后,尽快将这个报文段交给应用程序,而不是在缓冲区排队。
4)RST:重置连接标志,用于重置由于主机崩溃或其他原因而出现错误的连接。或者用于拒绝非法的报文段请求和拒绝连接请求。
5)SYN:同步序列号,用于建立连接过程,在连接请求中,SYN=1和ACK=0表示该数据段没有使用捎带的确认域,而连接应答捎带一个确认,即SYN=1和ACK=1。
6)FIN: finish标志,用于释放连接,为1时表示发送方已经没有数据发送了,即关闭本方数据流。

窗口
滑动窗口大小,用来告知发送端接收端的缓存大小,以此控制发送端发送数据的速率,从而达到流量控制。窗口大小是一个16bit字段,因而窗口大小最大为65535。

校验和
奇偶校验,此校验和是对整个的TCP报文段,包括TCP头部和TCP数据,以 16位字进行计算所得。由发送端计算和存储,并由接收端进行验证。

紧急指针
只有当URG标置为1时紧急指针才有效。紧急指针是一个正的便宜量,和顺序号字段中的值相加表示紧急数据最后一个字节的序号。TCP的紧急方式是发送端向另一端发送紧急数据的一种方式。

选项和填充
最常见的可选字段是最长报文大小,又称为MSS,每个连接方通常都在通信的第一个报文段(为建立连接而设置SYN标志位1的那个段)中指明这个选项,它表示本端所能接收的最大报文段的长度。选项长度不一定是32位的整数倍,所以要加填充位,即在这个字段中加入额外的零,以保证TCP头是32的整数倍。

数据部分
TCP报文段的数据部分是可选的。在一个连接建立和一个连接终止时,双方交换的报文段仅有TCP首部。如果一方没有数据要发送,也使用没有任何数据的首部来确认收到的数据。在处理超时的许多情况中,也会发送不带任何数据的报文段。

TCP连接建立

image.png

上图描述了TCP建立连接的过程。假定主机A运行的是TCP客户端程序,主机B运行的是TCP服务器程序。最初两端的TCP进程都处于CLOSED状态。当A主动打开连接,B被动打开连接。B的TCP服务器进程先创建传送控制块TCB(存储每一个连接中的重要信息,如TCP连接表,到发送和接收缓存的指针,到重传队列的指针,当前的发送和接收序列号等等),准备接受客户端的连接请求。然后服务器进程就处于LISTEN状态,等待客户的连接请求。如有,立即做出响应。A的TCP客户端程序也是首先创建传送控制块TCB,然后向B发出连接请求报文段,这时首部中的同步位SYN=1,同时选择一个初始序号seq=x。TCP规定,SYN报文段(即SYN=1的报文段)不能携带数据,但要消耗掉一个序号。这时,TCP客户端进入SYN-SENT(同步已发送)状态。

B收到连接请求后,如同意建立连接,则向A发送确认。在确认报文段中应把SYN位和ACK位都置1,确认号是ack=x+1,同时也为自己选择一个初始序号seq=y。请注意,这个报文段也不能携带数据,但同样要消耗掉一个序号。这时TCP服务器进入SYN-RCVD(同步收到)状态。

TCP客户端收到B的确认后,还要向B给出确认。确认报文段的ACK置1,确认号ack=y+1,而自己的序号seq=x+1。TCP的标准规定,ACK报文段可以携带数据。但如果不携带数据则不消耗序号,在这种情况下,下一个报文段的序号仍是seq=x+1。这时,TCP连接已经建立,A进入ESTABLISHED(已建立连接)状态。当B收到A的确认后,也进入ESTABLISHED状态。

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

三次握手是为了防止失效的连接请求报文段突然又传到了服务端,因而产生错误。所谓“已失效的连接请求报文段”是这样产生的。考虑正常情况,A发出连接请求,但因连接请求报文段丢失而未收到确认。于是A再重传一次连接请求。后来A收到了确认,建立了连接。数据传输完毕后,就释放了连接。A共发送了两个连接请求报文段,其中第一个丢失,第二个到达了B。没有”已失效的连接请求报文段“。

现假定出现一种异常,即A发送的第一个连接请求报文段并没有丢失,而是再某些网络结点长时间滞留了,以致延误到连接释放以后的某个时间才到达B。本来这是一个早已失效的报文段,但B收到此失效的报文段后就误认为是A又发出一次新的连接请求。于是就向A发出确认报文段,同意建立连接。假定不采用三次握手,那么只要B发出确认,新的连接就建立了。由于A并没有发出连接的请求,因此不会理睬B的确认,也不会向B发送数据。但B却以为新的传输连接已经建立了,并一直等待A发来数据。B的许多资源就这样被白白消耗掉了。采用三次握手的办法可以防止上述现象的发生。

SYN攻击是典型的DDOS攻击,简述其原理

在三次握手的过程种,服务器发送SYN和ACK之后,收到客户端的ACK之前的连接称为半连接。此时服务器处于SYN_RCVD状态,收到客户端的ACK之后进入ESTABLISHED状态。SYN攻击就是利用这个时间间隔伪造大量不存在的IP地址向服务器不断发送SYN包,服务器回复确认包,并等待客户的确认。由于源地址不存在,服务器需要不断地重发直至超时,这些伪造的SYN包将长时间占用未连接队列,而正常的SYN请求被丢弃,目标系统运行缓慢,引起网络的严重瘫痪。因此大多数操作系统都限制半连接的数量。

TCP关闭连接

image.png

上图展示了TCP连接释放的过程。数据传输结束后,通信的双方都可以释放连接。现在A和B都处于ESTABLISHED状态。A的应用进程先向其TCP发出连接释放报文段,并停止再发送数据,主动关闭TCP连接。A把连接释放报文段首部的终止控制位 FIN置1,其序号seq=u,它等于前面已经传送过的数据的最后一个字节的序号加1。这时A进入FIN-WAIT-1状态,等待B的确认。请注意,TCP规定,FIN报文段即使不携带数据,它也小号一个序号。

B收到连接释放报文段后发出确认,确认号是ack=u+1,而这个报文段自己的序号是v,等于B前面已经传送过的数据的最后一个字节的序号加1。然后B进入CLOSE-WAIT状态。TCP服务器进程这时应通知高层应用进程,因而从A到B这个方向的连接就释放了,这时的TCP连接处于半关闭状态,即A已经没有数据要发送了,但B若发送数据,A仍要接收。也就是说,从B到A这个方向的连接并未关闭,这个状态可能会持续一段时间。

A收到来自B的确认后,就进入FIN-WAIT-2状态,等待B发出的连接释放报文段。若B已经没有要向A发送的数据,其应用进程就通知TCP连接释放。这时B发出的连接释放报文段必须使FIN=1。现假定B的序号为w(在半关闭状态可能又发送了一些数据)。B还必须重复上次已发送过的确认号ack=u+1。这时B就进入LAST-ACK(最后确认)状态,等待A的确认。

A在收到B的连接释放报文后,必须对此发出确认。在确认报文段中把ACK置1,确认号ack=w+1,而自己的序号是seq=u+1。然后进入到TIME-WAIT状态。请注意,现在TCP连接还没有释放掉,必须经过时间等待计时器设置的时间2MSL后,A才进入到CLOSED状态。时间MSL叫做最长报文段寿命(Maximum Segment Lifetime)。RFC793建议设为2分钟。但这完全是从工程上考虑,对于现在的网络,MSL=2分钟可能太长了。因此TCP允许不同的实现可根据具体情况使用更小的MSL值。因此,从A进入到TIME-WAIT状态后,要经过四分钟才进入到CLOSED状态,才能开始建立下一个新的连接。当A撤销相应的传输控制块TCB后,就结束了这次的TCP连接。

为什么需要TIME-WAIT状态,即为什么需要等待2MSL?

MSL是一个报文段在网络上的最大的生存时间。
这里有两个原因需要等待2MSL:
第一,为实现TCP这种全双工连接的可靠释放。如何客户端在发完ACK之后直接进入CLOSED状态,若由于某种原因这个ACK丢失,那么服务器由于超时将重传FIN包,而此时客户端已经关闭连接,就找不到与重发的FIN包对应的连接,最后服务器收到的将是RST而不是ACK,服务器以为是连接错误而把问题上报给上层。这样的情况虽然不会导致数据丢失,但是却导致TCP协议不可靠。因此,客户端发完ACK后必须维护这条连接直至2MSL的时间结束。

第二,若不存在TIME-WAIT阶段,若有一个新的四元组建立一条新的TCP连接。由于TCP协议栈无法区分前后两条连接是否相同,在它看来,这条连接跟上一个关闭的连接使用的端口完全相同。而等待2MSL的时间,保证网络中旧的数据包已经完全消失,这样建立新的连接时可以使用旧的端口号,避免两次连接数据错乱的情况。

为什么TCP建立连接时是三次握手,而关闭连接时是四次挥手?

这是由于TCP传输协议是全双工的原因造成的。
在建立连接时,服务器收到客户端的SYN包后,可以将应答的ACK包和同步的SYN包放在同一个报文段里发送给客户端。但在关闭连接时,当收到对方的FIN包后,仅仅表示对方没有数据传给你了,并不表示你的所有数据都已经传送给了对方,因此不必马上关闭SOCKET,先发送一个ACK包确认已收到对方的关闭请求。然后等你的所有数据都发送完了再发送一个FIN包给对方表示同意关闭连接,因此ACK和FIN需要分开发送,故此连接多了一个交互过程。

TCP的流量控制

如果发送的太快,而接收方来不及接收,这样的情况就有可能导致数据丢失。所谓流量控制就是控制发送方的速率,不要让其发送的太快,使接收方来得及接收。TCP利用滑动窗口协议实现流量控制。

滑动窗口协议允许发送方和接收方各自设置自己的缓存区大小,并且发送方在停止等待确认前可以连续发送多个分组。由于发送方不必每发一个分组就停下来等待确认,因此可以提高传输效率。
1. 可变滑动窗口
设 A向B发送数据,B告知A当前我的rwnd=400,那么发送方A得发送窗口不能超过接收方得接收窗口大小。注意,窗口大小得单位是字节,ACK是却认为,ack是确认号。

image.png

如上图所示A向B发送数据。在连接建立时,B告诉A接收窗口rwnd(receiver window)= 400,单位字节,因此发送方A的发送窗口不能400。
可以看出,B向A发送的三个报文段都设置了 ACK = 1以保证字段有效,后面的rwnd值就是接收方对发送方的三次流量控制。
第一次把窗口设置为300 ,第二次100 ,最后一次为 0,即不允许发送方再发送数据的状态。

但是当某个ACK报文丢失了,就会出现A等待B确认,并且B等待A发送数据的死锁状态。为了解决这种问题,TCP引入了持续计时器(Persistence timer),当A收到rwnd=0时,就启用该计时器,时间到了则发送一个1字节的探测报文,询问B是很忙还是上个ACK丢失了,然后B回应自身的接收窗口大小,返回仍为0(A重设持续计时器继续等待)或者会重发rwnd=x。

2. 拥塞控制
2.1 慢开始和拥塞避免
2.1.1 慢开始原理
(1)在主机刚刚开始发送报文段时可先将拥塞窗口 cwnd 设置为一个最大报文段 MSS 的数值。
(2)在每收到一个对新的报文段的确认后,将拥塞窗口增加至多一个 MSS 的数值。
(3)用这样的方法逐步增大发送端的拥塞窗口 cwnd,可以使分组注入到网络的速率更加合理。
2.1.2 实例讲解

20130923092139371.jpeg

注:图中窗口的单位都是报文段
(1)当 TCP 连接进行初始化时:
发送窗口:swnd = 1
慢开始阈值:ssthresh = 16
(2)发送端收到 ACK1 (确认 M0,期望收到 M1)后,将 cwnd 从 1 增大到 2,于是发送端可以接着发送 M1 和 M2 两个报文段(指数增长)
(3)接收端发回 ACK2 和 ACK3。发送端每收到一个对新报文段的确认 ACK,就把发送端的拥塞窗口加 1。现在发送端的 cwnd 从 2 增大到 4,并可发送 M4 ~ M6共 4个报文段。(指数增长)
(4)当swnd >= ssthresh,swnd执行拥塞避免算法,swnd窗口按线性规律增长。 (加法增大)
(5)当发送 超时,此时swnd = 24 :
ssthresh = swnd/2 = 12;(乘法减小)
swnd = 1
(6)重复地2步。
2.2 快重传和快恢复
2.2.1 快重传
发送端只要一连收到三个重复的 ACK 即可断定有分组丢失了,就应立即重传丢失的报文段而不必继续等待为该报文段设置的重传计时器的超时
2.2.2 快恢复
(1) 当发送端收到连续三个重复的 ACK 时,就重新设置慢开始门限 ssthresh。
(2) 与慢开始不同之处是 swnd 不是设置为 1,而是设置为 ssthresh + 3 * MSS。
(3) 若收到的重复的 ACK 为 n 个(n > 3),则将 cwnd 设置为 ssthresh + n * MSS。
(4) 若发送窗口值还容许发送报文段,就按拥塞避免算法继续发送报文段。
(5) 若收到了确认新的报文段的 ACK,就将 swnd 缩小到 ssthresh。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,378评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,356评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,702评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,259评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,263评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,036评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,349评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,979评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,469评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,938评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,059评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,703评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,257评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,262评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,485评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,501评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,792评论 2 345

推荐阅读更多精彩内容