传输控制协议
(Transmission Control Protocol,TCP
):提供⾯向连接的、可靠的数据传输服务,数据传输的基本单位是报⽂段(segment)⽤户数据报协议
(User Datagram Protocol,UDP
):提供⽆连接的、尽最⼤努⼒的数据传输服务,但不保证数据传输的可靠性,数据传输的基本单位是⽤户数据报。从上图中可以看出, TCP/IP
模型⽐ OSI
模型更加简洁,它把 应⽤层/表示层/会话层
全部整合为了 应⽤层
。
在每⼀层都⼯作着不同的设备,⽐如我们常⽤的交换机就⼯作在数据链路层的,⼀般的路由器是⼯作在⽹络层的。
在每⼀层实现的协议也各不同,即每⼀层的服务也不同,下图列出了每层主要的传输协议:
同样, TCP/IP
五层协议的通信⽅式也是对等通信:
TCP
和 UDP
都是传输层协议,他们都属于TCP/IP
协议族:
UDP的全称是⽤户数据报协议,在⽹络中它与TCP协议⼀样⽤于处理数据包,是⼀种⽆连接的协议。在OSI模型中,在传输层,处于IP协议的上⼀层。UDP有 不提供数据包分组、组装和不能对数据包进⾏排序的缺点
,也就是说,当报⽂发送之后,是⽆法得知其是否安全完整到达的。
它的特点如下:
UDP在传输数据之前不需要先建⽴连接,远地主机的运输层在接收到UDP报⽂后,不需要确认,提供不可靠交付。总结就以下四点:
TCP 的可靠传输机制是基于连续 ARQ 协议
和滑动窗⼝协议
的。
TCP 协议在发送⽅维持了⼀个发送窗⼝,发送窗⼝以前的报⽂段是已经发送并确认了的报⽂段
,发送窗⼝中包含了已经发送但未确认的报⽂段
和允许发送但还未发送的报⽂段
,发送窗⼝以后的报⽂段是缓存中还不允许发送的报⽂段
。当发送⽅向接收⽅发 送报⽂时,会依次发送窗⼝内的所有报⽂段,并且设置⼀个定时器,这个定时器可以理解为是最早发送但未收到确认的报⽂段
。 如果在定时器的时间内收到某⼀个报⽂段的确认回答,则滑动窗⼝,将窗⼝的⾸部向后滑动到确认报⽂段的后⼀个位置,此时如 果还有已发送但 没有确认的报⽂段
,则重新设置定时器,如果没有了则关闭定时器。如果定时器超时,则重新发送所有已经发送 但还未收到确认的报⽂段
,并将超时的间隔设置为以前的两倍
。当发送⽅收到接收⽅的三个冗余的 确认应答
后,这是⼀种指示, 说明该报⽂段以后的报⽂段很有可能发⽣丢失了,那么发送⽅会启⽤快速重传
的机制,就是当前定时器结束前,发送所有的已发 送但确认的报⽂段
。接收⽅使⽤的是累计确认
的机制,对于所有按序到达的报⽂段,接收⽅返回⼀个报⽂段的肯定回答。如果收到了⼀个乱序的报⽂ 段,那么接⽅会直接丢弃,并返回⼀个最近的按序到达的报⽂段的肯定回答。使⽤累计确认保证了返回的确认号之前的报⽂段都 已经按序到达了,所以发送窗⼝可以移动到已确认报⽂段的后⾯。发送窗⼝的⼤⼩是变化的,它是由接收窗⼝剩余⼤⼩
和⽹络中拥塞程度
来决定的,TCP 就是通过控制发送窗⼝的⻓度来控制报⽂段的发送速率
。
但是 TCP 协议并不完全和滑动窗⼝协议相同,因为许多的 TCP 实现会将失序的报⽂段给缓存起来,并且发⽣重传时,只会重传⼀个报⽂段,因此 TCP 协议的可靠传输机制更像是窗⼝滑动协议
和选择重传协议
的⼀个混合体。
由于TCP的下层⽹络(⽹络层)可能出现丢失
、重复
或失序
的情况,TCP协议提供可靠数据传输服务。为保证数据传输的正确性,TCP会重传其认为已丢失(包括报⽂中的⽐特错误)的包。TCP使⽤两套独⽴的机制来完成重传,⼀是基于时间,⼆是基于确认信息。
TCP在发送⼀个数据之后,就开启⼀个定时器,若是在这个时间内没有收到发送数据的ACK确认报⽂,则对该报⽂进⾏重传,在达到⼀定次数还没有成功时放弃并发送⼀个复位信号。
TCP的拥塞控制机制主要是以下四种机制:
(1)慢启动(慢开始)
(2)拥塞避免
(3)快速重传
(4)快速恢复
⼀般来说,流量控制就是为了让发送⽅发送数据的速度不要太快,要让接收⽅来得及接收
。TCP采⽤⼤⼩可变的滑动窗⼝进⾏流量控制,窗⼝⼤⼩的单位是字节。这⾥说的窗⼝⼤⼩其实就是每次传输的数据⼤⼩。
(1)三次握手
三次握⼿(Three-way Handshake)其实就是指建⽴⼀个TCP连接时,需要客户端和服务器总共发送3个包。进⾏三次握⼿的主要作⽤就是为了确认双⽅的接收能⼒和发送能⼒是否正常、指定⾃⼰的初始化序列号为后⾯的可靠性传送做准备
。实质上其实就是连接服务器指定端⼝,建⽴TCP连接,并同步连接双⽅的序列号和确认号,交换TCP窗⼝⼤⼩信息。
刚开始客户端处于 Closed 的状态,服务端处于 Listen 状态。
⾸部的同步位SYN=1,初始序号seq=x,SYN=1的报⽂段不能携带数据,但要消耗掉⼀个序号。
在确认报⽂段中SYN=1,ACK=1,确认号ack=x+1,初始序号seq=y
确认报⽂段ACK=1,确认号ack=y+1,序号seq=x+1(初始为seq=x,第⼆个报⽂段所以要+1),ACK报⽂段可以携带数据,不携带数据则不消耗序号。
TCP 三次握⼿的建⽴连接的过程就是相互确认初始序号的过程,告诉对⽅,什么样序号的报⽂段能够被正确接收。 第三次握⼿的作⽤是客户端对服务器端的初始序号的确认
。如果只使⽤两次握⼿,那么服务器就没有办法知道⾃⼰的序号是否 已被确认。同时这样也是为了防⽌失效的请求报⽂段被服务器接收,⽽出现错误的情况。
(2)四次挥手
刚开始双⽅都处于 ESTABLISHED 状态,假如是客户端先发起关闭请求。四次挥⼿的过程如下:
即发出连接释放报⽂段(FIN=1,序号seq=u),并停⽌再发送数据,主动关闭TCP连接,进⼊FIN_WAIT1(终⽌等待1)状态,等待服务端的确认
即服务端收到连接释放报⽂段后即发出确认报⽂段(ACK=1,确认号ack=u+1,序号seq=v),服务端进⼊CLOSE_WAIT(关闭等待)状态,此时的TCP处于半关闭状态,客户端到服务端的连接释放。客户端收到服务端的确认后,进⼊FIN_WAIT2(终⽌等待2)状态,等待服务端发出的连接释放报⽂段。
即服务端没有要向客户端发出的数据,服务端发出连接释放报⽂段(FIN=1,ACK=1,序号seq=w,确认号ack=u+1),服务端进⼊LAST_ACK(最后确认)状态,等待客户端的确认。
即客户端收到服务端的连接释放报⽂段后,对此发出确认报⽂段(ACK=1,seq=u+1,ack=w+1),客户端进⼊TIME_WAIT(时间等待)状态。此时TCP未释放掉,需要经过时间等待计时器设置的时间2MSL后,客户端才进⼊CLOSED状态。
那为什么需要四次挥⼿呢?
因为当服务端收到客户端的SYN连接请求报⽂后,可以直接发送SYN+ACK报⽂。其中ACK报⽂是⽤来应答的,SYN报⽂是⽤来同步的。但是关闭连接时,当服务端收到FIN报⽂时,很可能并不会⽴即关闭SOCKET,所以只能先回复⼀个ACK报⽂,告诉客户端,“你发的FIN报⽂我收到了”。只有等到我服务端所有的报⽂都发送完了,我才能发送FIN报⽂,因此不能⼀起发送,故需要四次挥⼿。
简单来说就是以下四步:
TCP 使⽤四次挥⼿的原因是因为 TCP 的连接是全双⼯的,所以需要双⽅分别释放到对⽅的连接,单独⼀⽅的连接释放,只代表不能再向对⽅发送数据,连接处于的是半释放的状态
。
最后⼀次挥⼿中,客户端会等待⼀段时间再关闭的原因,是为了防⽌发送给服务器的确认报⽂段丢失或者出错,从⽽导致服务器 端不能正常关闭
。