TCP/UDP


概念:

我们常用的网络通讯,比如浏览网页、软件聊天、以及观看的视频都是通过这两种协议来进行数据传输的。

TCP协议和UDP协议都工作在传输层,他们的目标都是在程序之间传输数据。数据可以是文本文件可以是视频,也可以是图片,对于TCP协议和UDP协议来说,都是一堆二进制数,并没有多大的区别。

TCP基于连接:打电话

1、电话接通
2、互相通话
3、结束挂断

UDP基于非连接:写信:

1、对方是否能收到
2、内容是否完整
3、顺序是都正确

区别:

UDP发送数据就是简单的把数据包封装一下,然后从网卡发出去就可以了,数据包之间并没有状态上的联系。正因为UDP这种简单的处理方式,导致它的性能损耗非常少,对于cpu、内存资源的占用也远小于TCP,但是对于网络传输过程中产生的丢包,UDP协议并不能保证,所以UDP在传输稳定性上要弱于TCP。

TCP:传输数据稳定可靠,适用于对网络通讯质量要求较高的场景,需要准确无误的传输给对方,比如传输文件、发送邮件、浏览网页等

UDP:速度快,但是可能产生丢包,所以适用于对实时性要求较高,但是对少量丢包,并没有太大要求的场景,比如域名查询、语音通话、视频直播等,UDP还有一个非常重要的应用场景,就是隧道网络,如VPN。

TCP的三次握手:

目的是为了建立可靠的通信连接

(1)第一次握手:当客户端向服务端发起连接时,会先发一包连接请求数据,过去询问一下,能否与你建立连接,这包数据我们称之为SYN包,并进入SYN_SEND状态,等待服务端确认。

(2)第二次握手:如果对端同意连接,则回复一包SYN+ACK包,此时服务端进入SYN_RECV状态(SYN_RECEIVED 正在处于连接的初始同步状态[收到对方的SYN,但还没收到自己发过去的SYN的ACK])。

(3)第三次握手:客户端收到后,回复一包ACK包,连接建立,客户端和服务端进入ESTABLISHED状态,完成三次握手。

为什么要三次握手而不是两次握手

服务端回复完SYN+ACK之后就建立连接,这是为了防止因为已失效的请求报文突然又传到服务器引起错误。

假设采用两次握手建立连接,客户端向服务端发送了一个SYN包,来请求建立连接,因为某些未知的原因,并没有到达服务器,在中间某个网络节点产生了滞留,为了建立连接,客户端会重发SYN包,这次的数据包正常送达,服务端回复SYN+ACK之后建立起了连接,但是第一包数据阻塞的网络节点突然恢复,第一包SYN包又送达到服务端,这是服务端会误认为是客户端又发起了一个新的连接,从而在两次握手之后,进入等待数据状态。服务端认为是两个连接,而客户端认为是一个连接,造成了状态不一致。如果在三次握手的情况下,服务端收不到最后的ACK包,自然不会认为连接建立成功,所以三次握手本质上来说就是为了解决网络信道不可靠的问题,为了能在不可靠的信道上,建立起可靠的连接。

TCP的四次挥手

为了保证在不可靠的网络链路中,进行可靠的连接断开确认。

处于连接状态的客户端和服务端,都可以发起关闭连接请求,此时需要四次挥手来进行连接关闭

1、第一次挥手:假设客户端主动发起连接关闭请求,他需要向服务端发起一包FIN包,表示要关闭连接,自己进入终止等待1状态(FIN_WAIT_1)。

2、第二次挥手:服务端收到FIN包,发送一包ACK包,表示自己进入了关闭等待状态,客户端进入终止等待 2状态(FIN_WAIT_2)。

3、第三次挥手:服务端此时还可以发送未发送的数据,而客户端还可以接收数据,待服务端发送完数据之后,发送一包FIN包,进入最后确认状态(LAST_ACK)。

4、第四次挥手:客户端收到之后回复ACK包,进入超时等待状态(TIME_WAIT),经过超时时间(持续2MSL时间长度)后关闭连接,而服务端收到ACK包后,立即关闭连接

为什么要等待2MSL?

MSL:报文段最大生存时间,它是任何报文段被丢弃前在网络内的最长时间。

有以下两个原因:

第一点:保证TCP协议的全双工连接能够可靠关闭:
第二点:保证这次连接的重复数据段从网络中消失

为什么连接的时候是三次握手,关闭的时候却是四次握手?

建立连接时因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。所以建立连接只需要三次握手。

由于TCP协议是一种面向连接的、可靠的、基于字节流的运输层通信协议,TCP是全双工模式。
这就意味着,关闭连接时,当Client端发出FIN报文段时,只是表示Client端告诉Server端数据已经发送完毕了。当Server端收到FIN报文并返回ACK报文段,表示它已经知道Client端没有数据发送了,但是Server端还是可以发送数据到Client端的,所以Server很可能并不会立即关闭SOCKET,直到Server端把数据也发送完毕。
当Server端也发送了FIN报文段时,这个时候就表示Server端也没有数据要发送了,就会告诉Client端,我也没有数据要发送了,之后彼此就会愉快的中断这次TCP连接。