初识网络协议:TCP和UDP

TCP和UDP是网络协议里面传输层的协议,也是非常重要的两个协议。至于什么是传输层,看下面这张图。

那么这两个协议有什么区别呢?

  1. TCP是面向连接的,UDP是面向无连接的,TCP需要三次握手,四次挥手,UDP不要。

  2. TCP提供可靠交付,通过TCP连接传输的数据,无差错、不丢失、不重复、并且按序到达。而UDP不保证不丢失,不保证按序到达。

  3. TCP是面向字节流的,而UDP是基于数据报的。

  4. TCP是可以拥有拥塞控制的,UDP没有。

  5. TCP是有有状态服务,精确记着发送了没有,接收了没有,发送到哪个了,应该接收哪个了,是无错的。而UDP则是无状态服务。

网络包发出到达目标机器后,发现MAC地址匹配,就把MAC头取下来,将剩下的包传给处理IP层的代码。把IP头取下来,发现目标IP匹配。IP头里面还有个8位协议,里面会存放数据的协议,到底是TCP还是UDP。于是,如果我们知道UDP或者TCP头的格式,就可以从数据里面将它解析出来。

IP数据报:

UDP头:

端口号表示发送进程和接收进程,因为是两端通信,所以有一个源端口号,一个目的端口号。发出去的包最终还是要回来的,不然就丢包了。这个端口号是用来区分应用程序的,很好理解。

UDP长度字段指的是UDP首部和UDP数据的字节长度,该字段的最小值为8字节(发送一份0字节的UDP数据报是OK的)。这个UDP长度是有冗余的。IP数据报长度指的是数据报全长(该值在IP数据报总长度指定),因此UDP数据报长度是全长减去IP首部的长度(该值在IP数据报首部长度字段指定)。

UDP校验和覆盖UDP首部和UDP数据。IP首部的校验和只覆盖IP的首部,而不覆盖IP数据报中的任何数据。TCP和UDP在首部都有覆盖它们首部和数据的校验和,UDP的校验和是可选的,而TCP的校验和是必需的。

TCP头:

首先,源端口号和目标端口号是必不可少的,这一点和UDP一样。如果没有这两个端口号,就不知道要把数据发给哪个应用。

序号是用来标识从TCP发送端向TCP接收端发送的数据字节流,它表示在这个报文段中的第一个数据字节。如果将字节流看作在两个应用程序间的单向流动,则TCP用序号对每个字节进行计数。序号是32bit的无符号数,从0开始到2^32 - 1后又从0开始。

当建立一个新的连接时,SYN标志变1。序号字段包含由这个主机选择的该连接的初始序号ISN(Initial Sequence Number)。该主机要发送数据的第一个字节序号为这个ISN加1,因为SYN标志消耗了一个序号(终止连接时,FIN标志也要占用一个序号)。

既然每个传输的字节都被计数,确认序号包含发送确认的一端所期望收到的下一个序号。因此,确认序号应当是上次已成功收到的数据字节序号加1。只有ACK标志为1时确认序号字段才有效。

发送ACK无需任何代价,因为32bit的确认序号字段和ACK标志一样,总是TCP首部的一部分。因此,一旦一个连接建立起来,这个字段总是被设置,ACK标志也总是被设置为1。

首部长度给出首部中32bit字的数目,占4位,单位是32位字,所以首部最大值为60字节((2^4 - 1) * 32 / 8 = 60)。然而没有任选字段,正常长度是20字节(32 * 5 / 8 = 20)。

在TCP首部中有6个标志比特,它们中的多个可同时被设置为 1。我们在这儿简单介绍它们的用法。

URG 紧急指针(urgent pointer)有效。

ACK 确认序号有效。

PSH 接收方应该尽快将这个报文段交给应用层。

RST 重建连接。

SYN 同步序号用来发起一个连接。这个标志和下一个标志将在第 1 8章介绍。

FIN 发端完成发送任务。

TCP的流量控制由连接的每一端通过声明的窗口大小来提供。窗口大小为字节数,起始于确认序号字段指明的值,这个值是接收端正期望接收的字节。窗口大小是一个16bit字段,最大为65535。

校验和覆盖了整个的TCP报文段:TCP首部和TCP数据。这是一个强制性的字段,一定是由发送端计算和存储,并由接收端进行校验。

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

最常见的可选字段是最长报文大小,又称为MSS(Maximum Segment Size)。每个连接方通常都在通信的第一个报文段(为建立连接而设置SYN标志的那个段)中指明这个选项。它指明本端所能接收的最大长度的报文段。

三次握手:

  1. 客户端发送一个SYN段指明客户打算连接的服务器的端口,以及初始序号(ISN)x

  2. 服务器发回包含服务器的初始序号y的SYN报文段作为应答。同时,将确认序号设置为客户端的ISN加1(x + 1)以对客户端的SYN报文段进行确认。一个SYN将占用一个序号。

  3. 客户端必须将确认序号设置为服务器的ISN加1(y + 1)以对服务器的SYN报文段进行确认。

三次握手后,建立TCP连接,就可以传输数据了。建立一个连接需要三次握手,而终止一个连接需要四次挥手。

四次挥手:

  1. 首先进行关闭的一方(即发送第一个FIN)将执行主动关闭,而另一方(收到这个FIN)将执行被动关闭。

  2. 主动关闭方发起终止连接,它将导致TCP客户端发送一个FIN以及序号p。

  3. 当服务器收到这个FIN,它发回一个ACK,确认序号为收到的序号加1。和SYN一样,一个FIN将占用一个序号。同时TCP服务器还向应用程序传一个文件结束符,接着这个服务器程序就会关闭它的连接,导致它向客户端发送一个FIN,客户端必须返回一个ACK,并且确认序号设置为收到的序号加1。

当客户端收到服务器的第一个ACK时,会进入FIN-WAIT2状态,可如果服务器挂了,不能再同时发送一个FIN,那么客户端将永远在这个状态。TCP协议里面没有对这个状态的处理,但Linux里面有,可以调整tcp_fin_timeout这个参数,设置一个超时时间。

如果服务器没有挂,发送了FIN到达客户端,客户端收到FIN后会发送ACK给服务器。在这里为了保证服务端能收到ACK,在客户端发送ACK后让其处在TIME-WAIT状态,为的是等待足够长的时间。这样假如服务器没有收到ACK,会重发FIN,客户端收到FIN后也会重发ACK。等待时间设为2MSL(Maximum Segment Lifetime),报文最大生存时间,它是任何报文在网络上存在的最长时间,超过这个时间报文将被丢弃。因为TCP报文是基于IP协议的,而IP头中有一个TTL域,是IP数据报可以经过的最大路有数,每经过一个处理它的路由器此值就减1,当此值为0则数据报将被丢弃,同时ICMP报文通知源主机。协议规定MSL为2分钟,实际应用中常用的是30秒,1分钟和2分钟等。

TCP状态机:

TCP和UDP的使用场景:

从上文可以看出来TCP比UDP复杂得许多,这样也导致它的性能开销远大于UDP。而TCP是面向连接的,有各种机制保证其准确性。

所以UDP适用于对速度有要求而对精准性要求不高的应用,如即时通讯、在线视频、网络直播等。

TCP适用于对速度没有太大要求,但对精准性有较高要求的。如文件传输、发送接收邮件、远程登录等。

 

参考资料:《趣谈网络协议》、《TCP-IP详解卷一:协议》

posted @ 2020-02-28 11:11  灯无焰  阅读(482)  评论(0编辑  收藏  举报