一、TCP协议和UDP协议的区别
1、一般区别
- TCP是面向连接的,传输数据保证可靠性和安全性;TCP协议是非面向连接的,是不可靠但高效率的协议。
- TCP占用资源多而UDP占用少。
- TCP是流模式而TCP是数据报模式。(可以这样理解:TCP是面向连接的,用打电话的过程来类比,就是通信双方是互相明确的,所以进行的是“你一句我一句”的交流,TCP整个通信过程间有一个缓存区,由于通信主体明确,因此可以断断续续地进行交流,数据好比水流,知道源头和目的地,因此称为流模式。反过来,UDP是非面向连接的,好比写信的过程,假设我们只要知道佩奇的地址,我们就能写信给佩奇,而佩奇却不认识我们。这样发起通信方的身份是不明确的,每个发送端的信息都不能和别的发送端混淆,不然会造成数据失效,所以UDP要对数据进行“打包”发送,是面向报文的,就像写信需要用信封套起来,不然只发送数据甚至数据混合会变得毫无意义,就像qq群的匿名聊天,这不扯皮吗?)
- TCP和UDP的应用场景和编程方式也有很大差别,此处不再赘述。
2、TCP的粘包和UDP的丢包
TCP粘包现象:TCP粘包是指发送方发送的若干包数据到接收方接收时粘成一包,从接收缓冲区看,后一包数据的头紧接着前一包数据的尾。
粘包原因:
- 发送端:TCP默认会使用Nagle算法。而Nagle算法主要做两件事:1)只有上一个分组得到确认,才会发送下一个分组;2)收集多个小分组,在一个确认到来时一起发送。所以,正是Nagle算法造成了发送方有可能造成粘包现象。
- 接收端:TCP接收到分组时,并不会立刻送至应用层处理,或者说,应用层并不一定会立即处理;实际上,TCP将收到的分组保存至接收缓存里,然后应用程序主动从缓存里读收到的分组。这样一来,如果TCP接收分组的速度大于应用程序读分组的速度,多个包就会被存至缓存,应用程序读时,就会读到多个首尾相接粘到一起的包。
粘包处理:如果黏在一起的包是同一个整体,即同意部分数据分割而来的,那么就不用进行处理。如果是不同部分的数据粘到一起,就需要进行粘包解决:
- 发送端导致:使用TCP_NODELAY选项来关闭Nagle算法。
- 接收端导致:暂无。
- 统一解决(应用层):可以解决接收方造成的粘包问题,还能解决发送方造成的粘包问题。
解决方法就是循环处理:应用程序在处理从缓存读来的分组时,读完一条数据时,就应该循环读下一条数据,直到所有的数据都被处理;但是如何判断每条数据的长度呢?
两种途径:
1)格式化数据:每条数据有固定的格式(开始符、结束符),这种方法简单易行,但选择开始符和结束符的时候一定要注意每条数据的内部一定不能出现开始符或结束符;
2)发送长度(推荐):发送每条数据的时候,将数据的长度一并发送,比如可以选择每条数据的前4位是数据的长度,应用层处理时可以根据长度来判断每条数据的开始和结束。
UDP丢包现象:丢包现象即使用UDP发送时,由于不可靠连接方式,收到各种因素影响,数据包可能会在接受过程中丢失一部分,从而导致数据不完整。
UDP丢包原因:
- 发送端:发送的包太大导致send方法无法正常切割为小包导致丢包、发送的包太大超过缓存设置也会出现对包、发送频率太快导致接收端未接受或溢出缓冲区而丢包。
- 接收端:处理时间过长导致丢包。
- 其他:网络等问题。
UDP丢包处理:
- UDP的缺陷在于丢包和乱序问题,一般视情况进行处理,而发送的时候也需要注意上述导致丢包的问题。