区别:
- tcp面向连接的,可靠性高;udp无连接的,可靠性较低
- tcp是连接的通信,需要有三次握手、四次挥手等过程,会有延时,实时性差;udp无连接,因而实时性较强;
- tcp连接只能是点到点的;udp支持一对一、一对多、多对一、多对多的交互通信。
因而,在应用方面,对实时性要求高和高速传输的场合下需要使用udp,传输大量数据且对可靠性要求高的情况下应该使用tcp。
TCP三个阶段(TCP是全双工):
- 连接建立
- 数据传送
- 连接释放
三次握手
-
客户端发送一个tcp的syn标志位置为1的包(连接请求),指明客户打算连接的服务器的端口
即“A给B打电话说,你可以听到我说话吗?”
-
服务端收到请求,返回syn和ack标志位同时致为1(授予连接)的确认包,并为这次连接分配资源
即“B收到了A的信息,然后对A说:我可以听得到你说话啊,你能听得到我说话吗?”
-
客户端确认连接,发送确认包(syn为0,ack为1)
即“A收到了B的信息,然后说可以的,我要给你发信息啦!”
四次挥手:
中断连接端可以是客户端也可以是服务端
假设是客户端发起的中断连接请求,
- 客户端发送fin报文
- 服务端接收到fin报文后,意思是说:“客户端已经没有数据要发送给你了”,但是,如果此时服务端有数据未发送完成,则不必着急关闭socket,可以继续发送数据,所以服务端先发送ack,告诉客户端“收到了客户端刚才的关闭连接请求,但是服务端还有数据没发送,所以请客户端继续等我的消息”
- 此时客户端就进入了++fin_wait状态++,等待服务端的fin报文
- 服务端完成工作后,向客户端发送fin报文,告诉客户端已经发送完数据,可以关闭连接了
- 客户端接收到服务端的fin报文,就知道可以关闭连接了,但是还是不相信网络,怕服务端不知道要关闭,所以客户端发送ack给服务端后进入了++time_wait状态++,如果服务端没有收到ack则可以重传
- 服务端收到ack后,就知道可以关闭连接了,或者等待了2ms后依然没有收到回复,则证明服务端已经正常关闭了,此时客户端也会关闭连接
就这样,tcp连接就完成了关闭。
为何TCP建立连接是三个交互,不能只有两次吗?亦或者为何不是四次?
-
只有两次的情况
可能性只会发生在去掉最后一次,而最后一次ACK响应的重要性在于使得服务端确认了客户端能接收到信息,确认连接是正确建立的。
在没有最后一次连接的情况下,会导致这么一种情况,客户端A发出连接请求,此时请求报文丢失而未等到确认。于是A再次重传了连接请求,建立了连接。数据传输完毕后,释放了连接。假设第一个请求只是因为网路节点长时间滞留了,使得它在第二个连接释放后才到达B服务器,那么B会以为这是一个新的连接请求,于是就向A发了个连接确认,但这时候需要注意了:由于没有最后一次的确认B会一厢情愿的以为连接已经建立,可A一看那个B发送的报文并不明白这是什么,会直接丢掉。但B却还一直等着A给他发数据,就这样B浪费了资源。
不过实际情况不是如此的,B也不会一直等着,因为有保活定时器
-
有四次的情况
这个道理很显然,既然3次双方都已经确认了连接可行并且是期望的,第4次显然是浪费了资源
四次挥手为何要有TIME_WAIT的状态
- 保证最后一个的一个ACK报文能到达服务端B(B 被动关闭的一方)。这个ACK报文有可能丢失,因而使得处在LAST_ACK状态得不到对已发送的FIN+ACK报文的确认,B会超时重传这个FIN+ACk(LAST_ACK状态下是会有超时重传的),而A就能在这TIME_WAIT时间(2MSL)里收到这个重传的报文,A就可以重传一次确认,如果没有这个TIME_WAIT,那B重传的FIN_ACK,可A早就走了,自然不会再重发确认,这样B就无法按照正常步骤进入CLOSE状态。
- 第二是防止“已失效的报文连接请求”,A在TIME_WAIT中,经过这2MSL的时间,就可以使本链接持续的时间内产生的所有连接消失,这样就可以使下一个新的连接中不会出现这样旧的连接请求报文段。
当然了,还可以发现,如果服务器如果先关闭,若现在立马再次启动服务器,就会报错说这个端口号被占用着,那就是因为有这个TIME_WAIT