Skip to content

Latest commit

 

History

History
138 lines (77 loc) · 10.5 KB

TCP和UDP.md

File metadata and controls

138 lines (77 loc) · 10.5 KB

TCP和UDP

TCP用于可靠传输的情况,应用于文件传输,重要状态更新等场景。

UDP用于对高速传输和实时性要求较高的通信领域,例如早期的QQ、视频传输等等。


1 TCP简介

TCP协议全称:传输控制协议。

就是对数据的传输进行一定的控制。

正常情况下,tcp需要经过三次握手建立连接,四次挥手断开连接。


1.1 TCP的三次握手

过程如图:

第一次:

客户端 -> 服务器 此时服务器知道要建立连接了

第二次:

服务器 -> 客户端 此时客户端知道服务器收到连接请求了

第三次:

客户端 -> 服务器 此时服务器知道客户端收到了自己的响应

最后就可以建立连接。

详细的流程如下:

一开始,客户端和服务器都处于CLOSE状态。

此时,客户端向服务器主动发出连接请求,服务器被动接收连接请求。

  1. TCP服务器进程先创建传输控制块TCB。服务器进入LISTEN监听状态。
  2. TCP客户端进程也是创建传输控制块TCB,然后向服务器发出连接请求报文,
  3. 报文首部中的同步标志位SYN=1,同时选择一个初始序列号seq=x,此时,TCP客户端进程进入了SYN-SENT(同步已发送)状态。
  4. TCP服务器收到请求报文后,如果同意连接,则发出确认报文。确认报文中的ACK=1,SYN=1,确认序号是x+1,同时自己也要初始化一个序列号seq=y,TCP服务器进入了SYN-RCVD(同步收到)状态。
  5. TCP客户端进程收到确认后,要向服务器给出确认,确认报文的ACK=1,确认序号是y+1,自己的序列号是x+1.
  6. 此时,TCP连接建立,客户端进入ESTABLISHED(已建立连接)状态,当服务器收到客户端的确认后也进入ESTABLISHED状态。双方就开始通信了。

那为什么不用两次就好?

  • 主要是为了防止已经失效的连接请求报文突然又传送到了服务器,从而产生错误。如果使用的是两次握手,假如有种情况,客户端发送第一个请求后,可能网络中滞留时间太长了,由于TCP的客户端迟迟没有收到确认报文,以为服务器没有收到,此时重新向服务器发送这条报文,此后客户端和服务器经过两次握手完成连接,传输数据,然后关闭连接。此时之前的滞留的连接又突然恢复了,发送到了服务器,这个报文本该是失效的,但是两次握手的机制又让客户端和服务器连接起来,这就导致了不必要的错误和资源的浪费。
  • 如果采用的是三次握手,就算是那一次失效的报文传送过来了,服务器收到了那条失效报文并且回复了确认报文,但是客户端不会再次发出确认,由于服务器收不到确认,就知道了客户端没有请求连接。

那为什么不用四次?

  • 因为三次已经可以满足需求了,四次就多余了。

1.2 TCP的四次挥手

过程如图:

详细的流程如下:

数据传输完毕后,双方都可以释放连接。此时客户端和服务器都是处于ESTABLISHED状态,然后客户端主动断开连接,服务器被动断开连接。

  1. 客户端进程发出连接释放报文,并且停止发送数据。释放数据报文首部,FIN=1,其序列号为seq=u(前面已经传送过来的数据最后一个字节的序号加1),此时客户端进入FIN-WAIT-1(终止等待1)状态。
  2. 服务器收到连接释放报文,发出确认报文,ACK=1,确认序号为u+1,并且带上自己的序列号seq=v,此时服务器就进入了CLOSE-WAIT(关闭等待)状态。TCP服务器通知高层的应用进程,客户端向服务器的方向就要释放了,这时候处于半关闭状态,即客户端已经没有数据要发送了,但是服务器若发送数据,客户端依然要接受,这个状态还要持续一段时间,也就是CLOSE-WAIT状态持续的时间。
  3. 客户端收到服务器的确认请求后,此时客户端就进入了FIN-WAIT-2(终止等待2)状态,等待服务器发送连接释放报文(在这之前还需要接受服务器发送的最终数据)
  4. 服务器将最后的数据发送完毕后,就向客户端发送连接释放报文,FIN=1,确认序号为v+1,由于在半关闭状态,服务器很可能又发送了一些数据,假定此时的序列号为seq=w,此时,服务器就进入了LAST-ACK(最后确认)状态,等待客户端的确认。
  5. 客户端收到服务器的连接释放报文后,必须发出确认,ACK=1 ,确认序号为w+1,而自己的序列号是u+1,此时客户端就进入了TIME-WAIT(时间等待)状态,注意此时TCP连接还没有释放,必须经过2*MSL(最长报文段寿命)的时间后,当客户端撤销响应的TCB后,才进入CLOSED状态。
  6. 服务器只要收到了客户端发出的确认,立即进入CLOSED状态,同样,撤销TCB后,就结束了这次的TCP连接。可以看到,服务器结束TCP连接的时间,要比客户端要早一些。

为什么最后客户端还要等待2*MSL的时间呢?

  • 保证客户端发送的最后一个ACK报文能够到达服务器,因为这个ACK报文可能丢失,站在服务器的角度来看,我发已经发送后了FIN-ACK报文请求断开了,客户端没有给我回应,应该是发送的断开报文请求它没有收到,于是服务器又会重新发送一次,而客户端就能在这个2MSL时间段内收到这个重传的报文,接着给出回应报文,并且会重启2MSL计时器。
  • 防止类似与“三次握手”中提到了的“已经失效的连接请求报文段”出现在本连接中。客户端发送完最后一个确认报文后,在2MSL的时间中,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失,这样新的连接中不会出现旧连接的请求报文。

为什么建立是三次握手,关闭连接要四次挥手呢?

  • 建立连接的时候,服务器在LISTEN状态下,收到建立连接请求的SYN报文后,把ACK和SYN放在了一个报文里发送给客户端。而关闭时,服务器收到对方的FIN报文时,仅仅表示对方不再发送数据了,但是还能收到数据,而自己也未必全部数据都发送给对方了,所以自己可以立即关闭,也可以发送一些数据给对方后,再发送FIN报文给对方来表示同意现在关闭连接,因此,自己ACK和FIN一般都会分开发送,从而导致多了一次。

如果已经建立了连接,但是客户端突发故障了怎么办?

  • TCP设有一个保活计时器,显然,客户端如果出现故障,服务器不能一直等下去,不然浪费资源。服务器每次收到一次客户端的请求后,都会重新复位这个计时器,时间通常是设置为2小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔75秒发送一次,若一连发送10个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接。

2 UDP简介

使用UDP协议进行信息的传输之前不需要建立连接,换句话说就是客户端向服务器发送消息,客户端只需要给出服务器的ip地址和端口号,然后将信息封装到一个待发送的报文中并且发送出去,至于服务端是否存在,或者能否收到,客户端根本不用在意。

单播用于两个主机之间的端对端通信,广播用于一个主机对整个局域网上所有主机上的数据通信,单播和广播是两个极端,要么对一个主机进行通信,要么对整个局域网上的主机进行通信。实际情况下,经常需要对一组特定的主机进行通信,而不是整个局域网上的所有主机,这就是多播的用途。

对于广播,网络中的所有主机都会接收到一份数据副本。对于多播,消息只是发送到一个多播地址,网络只是将数据分发给那些表示想要接收发送到该多播地址的数据的主机。总的来说,只有UDP套接字允许广播或多播。


2.1 UDP广播

广播UDP与单播UDP的区别就是IP地址不同,广播使用广播地址255.255.255.255,将消息发送到同一个广播网络上的每个主机。注意本地广播信息不会被路由转发,不然转出去可能会引起网络瘫痪。

其实广播就是想向局域网内所有的人说话,但是广播还是要指明接收者的端口号,因为不可能接收者的所有端口都用来监听广播。

广播、多播、一对一播的服务端代码都是一样的,客户端代码也基本一样,只是地址不一样。

广播是:255.255.255.255 发现网卡所在网

多播是:192.168.1.255

一对一播是:192.168.1.101 或 其他具体地址


2.2 UDP多播

多播也称为“组播”,将网络中同一业务类型主机进行了逻辑上的分组,进行数据收发的时候,其数据仅仅在同一分组中进行,其他主机没有加入此分组不能收发对应的数据。

在广域网上广播的时候,其中的交换机和路由器只向需要获取数据的主机复制并转发数据。主机可以向路由器请求加入或退出某个组,网络中的路由器和交换机有选择地复制并传输数据,将数据仅仅传输给组内的主机。多播可以一次将数据发送到多个主机,又能保证不影响其他不需要的主机的其他通信。

对于传统的一对一单播,多播具有如下优点:

  • 具有同种业务的主机加入同一数据流,共享同一通道,节省了带宽和服务器的优点,具有广播的优点而又没有广播所需要的带宽。
  • 服务器的总带宽不受客户端带宽的限制,由于组播协议由接收者的需求来确定是否进行数据流的转发,所以服务器端的带宽是常量,与客户端的数据无关。
  • 与单播一样,多播是允许在广域网internet上进行传输的,而广播仅仅在同一局域网上才能进行。

多播的缺点:

  • 多播与单播相比,没有纠错机制,当发送错误的时候难以弥补,但是可以在应用层来实现。
  • 多播的网络支持存在缺陷,需要路由器及网络协议栈的支持。