一篇文章带你熟悉 TCP/IP协议-(一)-
https://segmentfault.com/a/11...
一篇文章带你熟悉 TCP/IP协议-(二)-
https://segmentfault.com/a/11...
一篇文章带你熟悉 TCP/IP协议-(三)-
https://segmentfault.com/a/11...
3、传输层中的 TCP 和 UDP
- TCP/IP 中有两个具备表明性的传输层协议,分别是 TCP 和 UDP。
- TCP 是面向链接的、可靠的流协议。流就是指不间断的数据结构,当应用程序采用 TCP 发送消息时,虽然能够保证发送的顺序,但仍是犹如没有任何间隔的数据流发送给接收端。TCP 为提供可靠性传输,实行“顺序控制”或“重发控制”机制。此外还具有“流控制(流量控制)”、“拥塞控制”、提升网络利用率等众多功能。
- UDP 是不具备可靠性的数据报协议。细微的处理它会交给上层的应用去完成。在 UDP 的状况下,虽然能够确保发送消息的大小,却不能保证消息必定会到达。所以,应用有时会根据本身的须要进行重发处理。
- TCP 和 UDP 的优缺点没法简单地、绝对地去作比较:TCP 用于在传输层有必要实现可靠传输的状况;而在一方面,UDP 主要用于那些对高速传输和实时性有较高要求的通讯或广播通讯。TCP 和 UDP 应该根据应用的目的按需使用。
1. 端口号
数据链路和 IP 中的地址,分别指的是 MAC 地址和 IP 地址。前者用来识别同一链路中不一样的计算机,后者用来识别 TCP/IP 网络中互连的主机和路由器。在传输层也有这种相似于地址的概念,那就是端口号。端口号用来识别同一台计算机中进行通讯的不一样应用程序。所以,它也被称为程序地址。编程
1.1 根据端口号识别应用
一台计算机上同时能够运行多个程序。传输层协议正是利用这些端口号识别本机中正在进行通讯的应用程序,并准确地将数据传输。
segmentfault
1.2 经过 IP 地址、端口号、协议号进行通讯识别
仅凭目标端口号识别某一个通讯是远远不够的。

缓存
- ① 和② 的通讯是在两台计算机上进行的。它们的目标端口号相同,都是80。这里能够根据源端口号加以区分。
- ③ 和 ① 的目标端口号和源端口号彻底相同,但它们各自的源 IP 地址不一样。
- 此外,当 IP 地址和端口号全都同样时,咱们还能够经过协议号来区分(TCP 和 UDP)。
1.3 端口号的肯定
- 标准既定的端口号:这种方法也叫静态方法。它是指每一个应用程序都有其指定的端口号。但并非说能够随意使用任何一个端口号。例如 HTTP、FTP、TELNET 等广为使用的应用协议中所使用的端口号就是固定的。这些端口号被称为知名端口号,分布在 0~1023 之间;除知名端口号以外,还有一些端口号被正式注册,它们分布在 1024~49151 之间,不过这些端口号可用于任何通讯用途。
- 时序分配法:服务器有必要肯定监听端口号,可是接受服务的客户端不必肯定端口号。在这种方法下,客户端应用程序彻底能够不用本身设置端口号,而全权交给操做系统进行分配。动态分配的端口号范围在 49152~65535 之间。
1.4 端口号与协议
- 端口号由其使用的传输层协议决定。所以,不一样的传输层协议可使用相同的端口号。
- 此外,那些知名端口号与传输层协议并没有关系。只要端口一致都将分配同一种应用程序进行处理。
2. UDP
- UDP 不提供复杂的控制机制,利用 IP 提供面向无链接的通讯服务。
- 而且它是将应用程序发来的数据在收到的那一刻,当即按照原样发送到网络上的一种机制。即便是出现网络拥堵的状况,UDP 也没法进行流量控制等避免网络拥塞行为。
- 此外,传输途中出现丢包,UDP 也不负责重发。
- 甚至当包的到达顺序出现乱序时也没有纠正的功能。
- 若是须要以上的细节控制,不得不交由采用 UDP 的应用程序去处理。
- UDP 经常使用于一下几个方面:1.包总量较少的通讯(DNS、SNMP等);2.视频、音频等多媒体通讯(即时通讯);3.限定于 LAN 等特定网络中的应用通讯;4.广播通讯(广播、多播)。
3. TCP
- TCP 与 UDP 的区别至关大。它充分地实现了数据传输时各类控制功能,能够进行丢包时的重发控制,还能够对次序乱掉的分包进行顺序控制。而这些在 UDP 中都没有。
- 此外,TCP 做为一种面向有链接的协议,只有在确认通讯对端存在时才会发送数据,从而能够控制通讯流量的浪费。
- 根据 TCP 的这些机制,在 IP 这种无链接的网络上也可以实现高可靠性的通讯( 主要经过检验和、序列号、确认应答、重发控制、链接管理以及窗口控制等机制实现)。
3.1 三次握手(重点)
- TCP 提供面向有链接的通讯传输。面向有链接是指在数据通讯开始以前先作好两端之间的准备工做。
- 所谓三次握手是指创建一个 TCP 链接时须要客户端和服务器端总共发送三个包以确认链接的创建。在socket编程中,这一过程由客户端执行connect来触发。
下面来看看三次握手的流程图:
服务器
- 第一次握手:客户端将标志位SYN置为1,随机产生一个值seq=J,并将该数据包发送给服务器端,客户端进入SYN_SENT状态,等待服务器端确认。
- 第二次握手:服务器端收到数据包后由标志位SYN=1知道客户端请求创建链接,服务器端将标志位SYN和ACK都置为1,ack=J+1,随机产生一个值seq=K,并将该数据包发送给客户端以确认链接请求,服务器端进入SYN_RCVD状态。
- 第三次握手:客户端收到确认后,检查ack是否为J+1,ACK是否为1,若是正确则将标志位ACK置为1,ack=K+1,并将该数据包发送给服务器端,服务器端检查ack是否为K+1,ACK是否为1,若是正确则链接创建成功,客户端和服务器端进入ESTABLISHED状态,完成三次握手,随后客户端与服务器端之间能够开始传输数据了。
3.2 四次挥手(重点)
- 四次挥手即终止TCP链接,就是指断开一个TCP链接时,须要客户端和服务端总共发送4个包以确认链接的断开。在socket编程中,这一过程由客户端或服务端任一方执行close来触发。
- 因为TCP链接是全双工的,所以,每一个方向都必需要单独进行关闭,这一原则是当一方完成数据发送任务后,发送一个FIN来终止这一方向的链接,收到一个FIN只是意味着这一方向上没有数据流动了,即不会再收到数据了,可是在这个TCP链接上仍然可以发送数据,直到这一方向也发送了FIN。首先进行关闭的一方将执行主动关闭,而另外一方则执行被动关闭。
下面来看看四次挥手的流程图:
网络
- 中断链接端能够是客户端,也能够是服务器端。
- 第一次挥手:客户端发送一个FIN=M,用来关闭客户端到服务器端的数据传送,客户端进入FIN_WAIT_1状态。意思是说"我客户端没有数据要发给你了",可是若是你服务器端还有数据没有发送完成,则没必要急着关闭链接,能够继续发送数据。
- 第二次挥手:服务器端收到FIN后,先发送ack=M+1,告诉客户端,你的请求我收到了,可是我还没准备好,请继续你等个人消息。这个时候客户端就进入FIN_WAIT_2 状态,继续等待服务器端的FIN报文。
- 第三次挥手:当服务器端肯定数据已发送完成,则向客户端发送FIN=N报文,告诉客户端,好了,我这边数据发完了,准备好关闭链接了。服务器端进入LAST_ACK状态。
- 第四次挥手:客户端收到FIN=N报文后,就知道能够关闭链接了,可是他仍是不相信网络,怕服务器端不知道要关闭,因此发送ack=N+1后进入TIME_WAIT状态,若是Server端没有收到ACK则能够重传。服务器端收到ACK后,就知道能够断开链接了。客户端等待了2MSL后依然没有收到回复,则证实服务器端已正常关闭,那好,我客户端也能够关闭链接了。最终完成了四次握手。
上面是一方主动关闭,另外一方被动关闭的状况,实际中还会出现同时发起主动关闭的状况,
具体流程以下图:
数据结构
3.3 经过序列号与确认应答提升可靠性
- 在 TCP 中,当发送端的数据到达接收主机时,接收端主机会返回一个已收到消息的通知。这个消息叫作确认应答(ACK)。当发送端将数据发出以后会等待对端的确认应答。若是有确认应答,说明数据已经成功到达对端。反之,则数据丢失的可能性很大。
- 在必定时间内没有等待到确认应答,发送端就能够认为数据已经丢失,并进行重发。由此,即便产生了丢包,仍然可以保证数据可以到达对端,实现可靠传输。
- 未收到确认应答并不意味着数据必定丢失。也有多是数据对方已经收到,只是返回的确认应答在途中丢失。这种状况也会致使发送端误觉得数据没有到达目的地而重发数据。
- 此外,也有可能由于一些其余缘由致使确认应答延迟到达,在源主机重发数据之后才到达的状况也家常便饭。此时,源主机只要按照机制重发数据便可。
- 对于目标主机来讲,反复收到相同的数据是不可取的。为了对上层应用提供可靠的传输,目标主机必须放弃重复的数据包。为此咱们引入了序列号。
- 序列号是按照顺序给发送数据的每个字节(8位字节)都标上号码的编号。接收端查询接收数据 TCP 首部中的序列号和数据的长度,将本身下一步应该接收的序列号做为确认应答返送回去。经过序列号和确认应答号,TCP 可以识别是否已经接收数据,又可以判断是否须要接收,从而实现可靠传输。

3.4 重发超时的肯定
- 重发超时是指在重发数据以前,等待确认应答到来的那个特定时间间隔。若是超过这个时间仍未收到确认应答,发送端将进行数据重发。最理想的是,找到一个最小时间,它能保证“确认应答必定能在这个时间内返回”。
- TCP 要求不论处在何种网络环境下都要提供高性能通讯,而且不管网络拥堵状况发生何种变化,都必须保持这一特性。为此,它在每次发包时都会计算往返时间及其误差。将这个往返时间和误差时间相加,重发超时的时间就是比这个总和要稍大一点的值。
- 在 BSD 的 Unix 以及 Windows 系统中,超时都以0.5秒为单位进行控制,所以重发超时都是0.5秒的整数倍。不过,最初其重发超时的默认值通常设置为6秒左右。
- 数据被重发以后若仍是收不到确认应答,则进行再次发送。此时,等待确认应答的时间将会以2倍、4倍的指数函数延长。
此外,数据也不会被无限、反复地重发。达到必定重发次数以后,若是仍没有任何确认应答返回,就会判断为网络或对端主机发生了异常,强制关闭链接。而且通知应用通讯异常强行终止。socket
3.5 以段为单位发送数据
- 在创建 TCP 链接的同时,也能够肯定发送数据包的单位,咱们也能够称其为“最大消息长度”(MSS)。最理想的状况是,最大消息长度正好是 IP 中不会被分片处理的最大数据长度。
- TCP 在传送大量数据时,是以 MSS 的大小将数据进行分割发送。进行重发时也是以 MSS 为单位。
- MSS 在三次握手的时候,在两端主机之间被计算得出。两端的主机在发出创建链接的请求时,会在 TCP 首部中写入 MSS 选项,告诉对方本身的接口可以适应的 MSS 的大小。而后会在二者之间选择一个较小的值投入使用。
3.6 利用窗口控制提升速度
- TCP 以1个段为单位,每发送一个段进行一次确认应答的处理。这样的传输方式有一个缺点,就是包的往返时间越长通讯性能就越低。
- 为解决这个问题,TCP 引入了窗口这个概念。确认应答再也不是以每一个分段,而是以更大的单位进行确认,转发时间将会被大幅地缩短。也就是说,发送端主机,在发送了一个段之后没必要要一直等待确认应答,而是继续发送。以下图所示:

- 窗口大小就是指无需等待确认应答而能够继续发送数据的最大值。上图中窗口大小为4个段。这个机制实现了使用大量的缓冲区,经过对多个段同时进行确认应答的功能。
3.7 滑动窗口控制

- 上图中的窗口内的数据即使没有收到确认应答也能够被发送出去。不过,在整个窗口的确认应答没有到达以前,若是其中部分数据出现丢包,那么发送端仍然要负责重传。为此,发送端主机须要设置缓存保留这些待被重传的数据,直到收到他们的确认应答。
- 在滑动窗口之外的部分包括未发送的数据以及已经确认对端已收到的数据。当数据发出后若如期收到确认应答就能够不用再进行重发,此时数据就能够从缓存区清除。
- 收到确认应答的状况下,将窗口滑动到确认应答中的序列号的位置。这样能够顺序地将多个段同时发送提升通讯性能。这种机制也别称为滑动窗口控制。
3.8 窗口控制中的重发控制在使用窗口控制中, 出现丢包通常分为两种状况:
- ① 确认应答未能返回的状况。在这种状况下,数据已经到达对端,是不须要再进行重发的,以下图:

- ② 某个报文段丢失的状况。接收主机若是收到一个本身应该接收的序列号之外的数据时,会针对当前为止收到数据返回确认应答。以下图所示,当某一报文段丢失后,发送端会一直收到序号为1001的确认应答,所以,在窗口比较大,又出现报文段丢失的状况下,同一个序列号的确认应答将会被重复不断地返回。而发送端主机若是连续3次收到同一个确认应答,就会将其对应的数据进行重发。这种机制比以前提到的超时管理更加高效,所以也被称为高速重发控制。
