一、自身角度
1.无连接和面向连接
UDP:“无连接”
在网络中使用UDP协议时,只需要提供对端的IP地址和端口号就可以与对端进行通信,并不需要和对端建立连接
TCP:“面向连接”
在网络中使用TCP协议时,不仅需要对端的IP地址和端口号,还需要通过“三次握手”建立连接,“四次挥手”断开连接
2.不可靠和可靠
UDP:不可靠。UDP没有提供使数据可靠传输的机制,UDP的报头中只有校验和,但是校验和只能检查报头信息是否出错不足以保证协议的可靠性
TCP:可靠,TCP的报头中添加了很多字段来保证协议的可靠性,如:序号、确认序号、窗口大小
(1)确认应答机制和超时重传机制
可以通过序号和确认序号,提供确认应答机制和超时重传机制处理在传输过程中的丢包问题,同时可以保证数据的按序到达,并且能够达到去除重复数据的效果
(2)流量控制机制
通过窗口大小显示自己接收缓冲区的大小,使对端在发送数据时控制速率,防止对端发送速率过大而自己的接收能力不足而导致的数据丢包。
(3)拥塞避免机制
避免发送效率过大而导致的网络拥塞,先发送少量数据探测网络状况,同时TCP为提升自身性能,还提供了滑动窗口、快重传、延迟应答、捎带应答机制。
3.面向数据报和面向字节流
UDP:面向数据报
在发送和接收数据时必须一个报文一个报文的进行,不能发送/接收半个报文UDP报头里面包含一个字段是16位的UDP总长度,根据总长度就可以确定每个UDP数据包的大小,读取数据按照大小来读,没有粘包问题
TCP:面向字节流
在发送和接收数据时不必要一个报文一个报文的进行,可以发送/接收半个报文,由于TCP是面向字节流的,也因此会导致粘包问题
4.没有发送缓冲区和有发送缓冲区
UDP:没有发送缓冲区,只有接收缓冲区;由于UDP是不可靠的,不需要将发送的数据保存至发送缓冲区再移交给内核(这样当数据丢包时,发送缓冲区的内容会再次向内核发送),而是直接调用sendto发送给内核 ,不保证可靠性,没有超时重传,那么UDP就不用保存他以前发送的数据,因此UDP就没有发送缓冲区
TCP:有接收缓冲区和发送缓冲区;TCP为了能够超时重传时需要重传的数据还在,那么TCP就需要把以前发送的数据进行缓存起来,方便以后重发,因此就需要发送缓冲区
5. 每一条TCP连接只能用于点点之间一对一进行,而UDP支持一对一、一对多、多对多的交互通信
6.TCP的粘包问题
粘包问题是指由于TCP是面向字节流的,发送和接收时不需要一个报文一个报文的进行,所以在应用层拿到数据时就会是一串连续的字符串,不知道哪里是一个数据包的开始,哪里是该数据包的结尾
解决粘包问题的关键在于明确两个包之间的边界:
(1)采用定长报文的方式,每次都按照固定的长度读取,如:UDP协议,在报头中有报头的长度
(2)采用自描述字段,如:HTTP协议报头中的Content_Length字段,在报头位置告诉报文的长度
(3)采用明显的分割符,如:HTTP协议报头与报文中的空行
二、数据结构(报头)
(1)TCP的报头默认占20字节,而UDP的报头占8字节,因此TCP比UDP要更耗资源
(2)UDP的报头有源端口号、目的端口号、16位校验和以及16位总长,TCP为了保证可靠性比UDP多的序号、确认序号、窗口大小还包括特别重要的6位标志位(URG、ACK、PSH、RST、SYN、FIN),TCP的报头多的这些内容为TCP保证可靠性提供了重要的依据
(3)UDP的报头里面包含一个16位总长度,使得UDP报文长度可以得到确定;但是TCP的报头里面只包含4位首部长度,这个只能确定TCP报头总长度但是不能确定TCP报文(包括TCP首部和TCP数据)总长度,因此TCP具有粘包问题
三、编程角度
(1)采用UDP编程比采用TCP编程要简单很多;
(2)服务器
调用socket创建一个套接字;调用bind函数,绑定端口号和IP地址到socket上; 当这两步做完之后UDP就可以与客户端进行数据传输,但是TCP还需要调用listen使得创建的套接字变为被动套接字可以一直监听客户端的到来,接下来调用accept一直阻塞等待客户端的连接,当有客户端连接之后此时accept返回一个新的文件描述符,这个文件描述符用来和客户端进行数据交互,此时客户端与服务器就可以进行数据交互。
(3)客户端
两者首先都需要:调用socket函数创建套接字,此时UDP的客户端就可以向服务器发送数据,但是TCP的客户端还需要调用connect 函数与TCP服务器建立连接,当连接建立成功之后,TCP客户端就可以向TCP服务器发送数据。
注意: UDP是可以调用connect函数的,但是UDP的connect函数和TCP的connect函数调用确是大相径庭的,这里没有三次握手过程。内核只是检查是否存在立即可知的错误(比如目的地址不可达),记录对端的IP和端口号,然后立即返回调用进程。
(4)TCP套接字可以采用write/read、recvfrom/sendto来进行数据的的读写,但是UDP套接字不能采用write/read,因为read和write是面向字节流的。
四、UDP如何保证可靠传输
(1)因为TCP的可靠性是由确认机制、重传机制、流量控制和拥塞控制来保证的;
(2)由于UDP协议不保证可靠性,如果想要UDP编程保证可靠性那么只能由用户层来实现,按照TCP可靠性保证机制来实现类似的机制就可以达到目的。
(3)用户自己指定一系列的机制用来保证可靠性:可以自己定制一个计时器,当计时器时间到了还没有收到对方发的消息,就要求重传;用于也可以自己对发送的数据进行编号,将收到的数据按照编号顺序存放,如果缺少就要求重传引入确认应答,保证数据被对方正确收到等。
五、个人小结
(1)不能因为UDP不保证可靠性就认为UDP对数据传输没有用途,但是因为UDP效率快,虽然不保证可靠性但是有时候传输的数据不要求完全可靠,因此UDP在视频传输方面可以有着重要的作用,因为丢失几个帧并不导致视频的观看。
(2)也不能因为TCP在保证可靠性的条件下做了很多的限制就认为TCP效率较低,TCP也有很多措施用来提升效率(滑动窗口、延迟应答、快重传、捎带应答)。
(3)因此不能从某一个机制的一些缺点来判定该机制的好坏,不同的机制有着不同的应用场景,选取合适的应用场景就可以发挥各自的优势。