TCP/IP(三):传输层TCP与UDP

TCP协议

  1. 概述
    TCP协议和UDP协议处于同一层:传输层,但是两者之间有很大的区别,TCP协议具有以下特点:

    • TCP提供可靠的数据传输服务,TCP是面向连接的,即数据在通信之间要先建立连接,结束通信时要释放连接,这也是后面所说的3次握手,4次挥手;
    • TCP是点对点的连接方式,即一条TCP连接两端只能是两个端点;
    • TCP提供可靠的,无差错的,不丢失,不重复,按顺序的服务;
    • TCP提供全双工通信,允许通信双方任何时候都能发送数据,TCP在连接的两端都设置有发送缓存和接收缓存;
    • TCP是面向字节流的,TCP传输的数据是一个一个字节的按序传输的,数据块与数据块之间没有边界信息,对于TCP来说,所有数据都是一样的,TCP不能区分数据的意义。

    这里写图片描述

  2. TCP报文结构:
    TCP 报文段的报头有前 20 字节的固定部分,后面 4n 字节是根据需要而添加的字段,下图是TCP完整的报文结构:

    这里写图片描述

    20 字节的固定部分,各字段功能说明:

    • 源端口和目的端口: 各占 2 个字节,分别写入源端口号和目的端口号。这和 UDP 报头有类似之处,因为都是运输层协议。
    • 序号: 占 4 字节序,序号范围[0,2^32-1],序号增加到 2^32-1 后,下个序号又回到 0。 TCP 是面向字节流的,通过 TCP 传送的字节流中的每个字节都按顺序编号,而报头中的序号字段值则指的是本报文段数据的第一个字节的序号。
    • 确认序号: 占 4 字节,期望收到对方下个报文段的第一个数据字节的序号。
    • 数据偏移: 占 4 位,指 TCP 报文段的报头长度,包括固定的 20 字节和选项字段。
    • 保留: 占 6 位,保留为今后使用,目前为 0。
    • 控制位: 共有 6 个控制位,说明本报文的性质,意义如下:
      URG 紧急:当 URG=1 时,它告诉系统此报文中有紧急数据,应优先传送(比如紧急关闭),这要与紧急指针字段配合使用。
      ACK 确认:仅当 ACK=1 时确认号字段才有效。建立 TCP 连接后,所有报文段都必须把 ACK 字段置为 1。
      PSH 推送:若 TCP 连接的一端希望另一端立即响应,PSH 字段便可以“催促”对方,不再等到缓存区填满才发送。
      RET 复位:若 TCP 连接出现严重差错,RST 置为 1,断开 TCP 连接,再重新建立连接。
      SYN 同步:用于建立和释放连接,稍后会详细介绍。
      FIN 终止:用于释放连接,当 FIN=1,表明发送方已经发送完毕,要求释放 TCP 连接。
    • 窗口: 占 2 个字节。窗口值是指发送者自己的接收窗口大小,因为接收缓存的空间有限。
    • 检验和: 2 个字节。和 UDP 报文一样,有一个检验和,用于检查报文是否在传输过程中出差错。
    • 紧急指针: 2 字节。当 URG=1 时才有效,指出本报文段紧急数据的字节数。
    • 选项: 长度可变,最长可达 40 字节。具体的选项字段,需要时再做介绍。
  3. TCP连接和释放:
    3.1. 三次握手
    这里写图片描述

    TCP三次握手过程:

    • 客户端发出请求连接报文段,其中报头控制位 SYN=1初始序号 seq=x。客户端进入 SYN-SENT(同步已发送)状态。
    • 服务端收到请求报文段后,向客户端发送确认报文段。确认报文段的首部中 SYN=1ACK=1确认号是 ack=x+1,同时为自己选择一个初始序号 seq=y。服务端进入 SYN-RCVD(同步收到)状态。
    • 客户端收到服务端的确认报文段后,还要给服务端发送一个确认报文段。这个报文段中 ACK=1确认号 ack=y+1,而自己的序号 seq=x+1。这个报文段已经可以携带数据,如果不携带数据则不消耗序号,则下一个报文段序号仍为 seq=x+1。
    • 至此 TCP 连接已经建立,客户端进入 ESTABLISHED(已建立连接)状态,当服务端收到确认后,也进入 ESTABLISHED 状态,它们之间便可以正式传输数据了。

    3.2. 四次挥手
    这里写图片描述

    TCP四次挥手过程:

    • 此时 TCP 连接两端都还处于 ESTABLISHED 状态,客户端停止发送数据,并发出一个 FIN 报文段。首部 FIN=1序号 seq=u(u 等于客户端传输数据最后一字节的序号加 1)。客户端进入 FIN-WAIT-1(终止等待 1)状态。
    • 服务端回复确认报文段,确认号 ack=u+1序号 seq=v(v 等于服务端传输数据最后一字节的序号加 1),服务端进入 CLOSE-WAIT(关闭等待)状态。现在 TCP 连接处于半开半闭状态,服务端如果继续发送数据,客户端依然接收。
    • 客户端收到确认报文,进入 FIN-WAIT-2 状态,服务端处理完数据后,发出 FIN 报文段,FIN=1,确认号 ack=u+1,然后进入 LAST-ACK(最后确认)状态。
    • 客户端回复确认确认报文段,ACK=1,确认号 ack=w+1(w 为半开半闭状态时,收到的最后一个字节数据的编号) ,序号 seq=u+1,然后进入 TIME-WAIT(时间等待)状态。

    注意此时连接还没有释放,需要时间等待状态结束后(4 分钟) 连接两端才会 CLOSED。设置时间等待是因为,有可能最后一个确认报文丢失而需要重传,下面具体阐述TIME-WAIT(时间等待)状态的原因:

    TIME_WAIT状态维持的时间是最长分节生命期的2倍,2MSL(MSL=30s~120s)

    • 原因一:可靠的实现TCP全双工连接的终止
      如果客户端在接收到服务器端的FIN后,发送的ACK分组在通路中丢失,由于超时重传机制,服务器端没有接受到来自客户端的应答,所以重新发送FIN,这时总共经历的时间最大可能为2MSL,当第二个FIN到达时,保证在客户端维护必要的状态信息确保能够发送最终的ACK,保证两边都能够关闭
    • 原因二:允许老的重复分节在网络中消逝
      如果关闭一个链接后,马上建立新的链接,这个链接的IP地址和端口号和刚关闭的链接相同,这时候如果上一个链接中重复的分节没有消逝,这时这个重复的分节就有可能被新的链接接收,所以为了防止旧链接中的分节能够消逝,不影响新链接,将TIME_WAIT设置为2倍的MSL。

    3.3. TIME-WAIT状态的带来的影响和解决方法
    由于TIME-WAIT状态的存在,使得socket可以进入和留存相当长一段时间,如果你的系统中有很多 socket 处于TIME-WAIT状态,那么当你需要创建新的 socket 连接的时候可能会受到影响,这也会影响到你的程序的扩展性。因为在一个TCP连接中,一个Socket如果关闭的话,它将保持TIME-WAIT状态大约 4分钟 。如果很多连接快速的打开和关闭的话,系统中处于TIME-WAIT状态的socket将会积累很多,你可以使用netstat命令查看处于TIME-WAIT状态的socket。由于本地端口数量的限制,同一时间只有有限数量的socket连接可以建立,如果太多的socket处于TIME_WAIT状态,你会发现,由于用于新建连接的本地端口太缺乏,将会很难再建立新的对外连接。在Linux中,可以通过设置SO_REUSEADDR允许连接重用,TIME-WAIT的存在是有它的理由的,通过缩短2MSL的时间或者使用SO-REUSEADDR允许连接重用并不总是好主意。如果你有能力去设计你的协议避免TIME-WAIT产生的问题的话,你就可以避免这里所有的问题。

  4. TCP可靠传输的实现:

    • (1) TCP 报文段的长度可变,根据收发双方的缓存状态、网络状态而调整。
    • (2) 当 TCP 收到发自 TCP 连接另一端的数据,它将发送一个确认。
    • (3) 当 TCP 发出一个段后,它启动一个定时器,等待目的端确认收到这个报文段,如果不能及时收到一个确认,将重发这个报文段。这就是稍后介绍的超时重传。
    • (4) TCP 将保持它首部和数据的检验和。如果通过检验和发现报文段有差错,这个报文段将被丢弃,等待超时重传。
    • (5) TCP 将数据按字节排序,报文段中有序号,以确保顺序的正确性。
    • (6) TCP 还能提供流量控制。TCP 连接的每一方都有收发缓存。TCP 的接收端只允许另一端发送接收端缓冲区所能接纳的数据。这将防止较快主机致使较慢主机的缓冲区溢出。

    超时重传机制很费时间,每发送一个数据报都要等待确认。在实际应用中的确不是这样的,真实情况是,采用了流水线传输:发送方可以连续发送多个报文段(连续发送的数据长度叫做窗口),而不必每发完一段就停下来等待确认。实际应用中,接收方也不必对收到的每个报文都做回复,而是采用累积确认方式:接收者收到多个连续的报文段后,只回复确认最后一个报文段,表示在这之前的数据都已收到。这样,传输效率得到了很大的提升。

UDP协议

用户数据报协议,它只在 IP 数据报服务之上增加了很少一点功能,它的主要特点有:
(1) UDP 是无连接的,发送数据之前不需要建立连接(而 TCP 需要),减少了开销和时延。
(2) UDP尽最大努力交付,不保证交付可靠性。
(3) UDP 是面向报文的,对于从网络层交付下来的 IP 数据报,只做很简单的封装(8 字节 UDP 报头),首部开销小。
(4) UDP 没有拥塞控制,出现网络拥塞时发送方也不会降低发送速率。这种特性对某些实时应用是很重要的,比如 IP 电话,视频会议等,它们允许拥塞时丢失一些数据,因为如果不抛弃这些数据,极可能造成时延的累积。
(5) UDP 支持一对一、一对多、多对一和多对多的交互通信。

UDP报文:
UDP 数据报可分为两部分:UDP 报头和数据部分。其中数据部分是应用层交付下来的数据。UDP 报头总共 8 字节,而这 8 字节又分为 4 个字段:

这里写图片描述

(1)源端口 2 字节 在对方需要回信时可用,不需要时可以全 0;
(2)目的端口 2 字节 必须,也是最重要的字段;
(3)长度 2 字节 长度值包括报头和数据部分;
(4)校验和 2 字节 用于检验 UDP 数据报在传输过程中是否有出错,有错就丢弃。

TCP与UDP的区别

面向报文的传输方式是应用层交给UDP多长的报文,UDP就照样发送,即一次发送一个报文。因此,应用程序必须选择合适大小的报文。若报文太长,则IP层需要分片,降低效率。若太短,会是IP太小。UDP对应用层交下来的报文,既不合并,也不拆分,而是保留这些报文的边界。这也就是说,应用层交给UDP多长的报文,UDP就照样发送,即一次发送一个报文。

面向字节流的话,虽然应用程序和TCP的交互是一次一个数据块(大小不等),但TCP把应用程序看成是一连串的无结构的字节流。TCP有一个缓冲,当应用程序传送的数据块太长,TCP就可以把它划分短一些再传送。如果应用程序一次只发送一个字节,TCP也可以等待积累有足够多的字节后再构成报文段发送出去。

这里写图片描述

TCP和UDP的对比:
这里写图片描述

这里写图片描述

  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值