使用UDP的应用程序如何实现可靠传输众所周知,UDP不可靠、不保证顺序 。
1、什么叫不可靠?A给B发送一个UDP数据报,该UDP数据报不一定被正确交付给接收端B,但因为网络质量等各种原因,可能丢包,IP数据报是尽力而为的交付,一切随缘 。
有没有办法保证,发送的UDP一定到达目的端?Sorry,保证不了,做不到 。
那TCP提供的可靠传输是什么意思?TCP提供的可靠传输并不是指不丢包,因为TCP也依赖IP(IP不可靠)实现数据报交付,TCP的可靠性是指丢掉的包会被重传,直到被正确投递,才会继续传输下一个数据报 。
那TCP是怎么做到可靠传输的呢?很简单,收报确认(ack)+丢包重传 。所以UDP如果要提供可靠传输,也可以参考TCP的实现机制,只是TCP是实现在内核层,而基于UDP的应用程序,可以把可靠传输做到应用层 。要做收报确认+丢包重传,需要一些额外的信息,比如包序列号之类,可以放到Payload,约定好这些额外信息在Payload中的结构布局即可 。
2、什么叫不保证顺序?A给B发送两个UDP数据报,两个UDP数据报会被封装为两个IP数据报,通过IP协议传输,因为两个IP数据报独立路由,所以哪个先到?不一定,看心情 。
有没有办法保证,UDP数据报按照发送端发送的时间顺序到达目的端?也Sorry,办不到 。
所以,TCP提供的顺序性,其实只是在接收端对IP数据报根据发送顺序重新排序,很显然,UDP要支持重排序,也需要一些额外信息,也只能通过payload携带,而不能像TCP一样(TCP首部的一些字段用于接收端重排序) 。
综上,UDP只提供最简单端主机上应用程序的端到端服务,其他的特性,如果要提供,那请参考TCP的思路去实现吧 。
这是有好处的:因为简单,所以开销很小 。而某些应用场景,可以容忍丢包、乱序,UDP就是很适合的 。保时捷是很好,但拉砖还是用拖拉机吧 。
UDP Socket编程UDP Socket网络编程的API不多,socket()用于创建套接字,close()用于关闭套接字,sendto()用于发送数据,recvfrom()用于接收数据 。
bind()顾名思义是绑定,TCP可以绑定,UDP也可以,bind用于UDP等于告诉内核:这个套接字跟网络远端的一个<IP,Port>对子关联上了 。以后就可以直接调用send()往那个<IP,Port>标识的主机上的进程发送UDP数据报了 。
而没有bind之前,只能通过sendto()接口(通过参数指定目的地) 。UDP套接字recv()返回的是UDP数据报的数据部分(Payload),不包括UDP数据报首部,这是因为UDP首部的字段用于分发或者校验,不需要透传给应用程序 。
使用UDP套接字开发的网络应用Server/Client,网络IO相关操作和流程如下图所示:
文章插图
UDP套接字编程
推荐阅读
- 深入探讨 MySQL 的 order by 优化
- 第一次有人把公司、企业、个体户说得这么有意思,好理解多了!
- 鉴别普洱茶的老生茶
- spring框架史上最全深入理解
- 让我们抓住春天的尾巴 深入的了解春茶
- 对Java中HashCode方法的深入思考
- java程序运行原理解析
- |职场权术,那些让人不理解的行为,蕴含着怎样的意义?
- 理解Java的三大特性之封装
- 一文让你理解 Lambda 表达式