可靠UDP
tcp为我们做了什么事情?
总得来说,tcp做了这几件事:
- 通过序列号和基于确认的超时重传机制,为上层提供了可靠的字节流服务;
- 通过滑动窗口、拥塞窗口提供了流量控制;
- 默认情况下,为了有效利用带宽,tcp的报文一次会尽量携带更多的数据。但与此同时,为了避免IP层的分片,又不会发送超过MTU大小的数据包。
udp为我们做了什么事情?
首先应该清楚的是,一个udp数据包仅仅是在IP数据包之上加了一个udp协议头。这个协议头十分精简,仅有的四个字段是:目的端口号、源端口号、数据包长度、校验和。通过sendto这个syscall发送一个udp数据包时,实际上就是包装成一个IP数据包然后直接发送出去。这里并不会像tcp那样在本地缓存数据,直到达到一个长度限制后再发送出去。另外由于有检验和,所以我们不需要在udp之上再做校验的事情了。
一个可靠的udp协议
在清楚tcp做了什么事后,我们就有了实现一个可靠udp的思路了。首先需要说明的是,在udp之上实现一个tcp是没有意义的。实现一个可靠的udp协议往往是,根据业务需要,牺牲掉一部分的tcp的功能,来换取更高的性能。但是,在动手造轮子之前,我们应该分清的是,哪些功能是tcp已经为我们实现了的,而哪些功能是要通过自己定制一个可靠udp来实现的。比如说,上述的第3条,这个特性有时候会造成tcp的延迟性,但是通常可以通过设置TCP_NODELAY来解决。
实现一个最基础的可靠udp通讯协议,我们只需要提供一个重传机制即可。在这我实现了一个简单的可靠udp协议,这个协议为每一个发送出去的udp数据包分配一个包id,每次接收方收到一个数据包时,都要回应发送方一个ack对应这个包id。协议通过这种确认机制来保证接收方能收到发送方发出的udp数据包,在发出的时候,发送方应该设置一个计时器,超时的话会重传数据包。
这个协议做的就是这么多,它仅能确保接收方能收到发送方的udp包,并没有做其它的事情。
具体来说它没做这些事情:
- 它没有保证包的有序性。发送方连续发送几个udp数据包,接收方可以以任何顺序收到这几个数据包。如果想要做到有序性,必须由应用层来完成。
- 它没做流量控制。发送方连续大量发送数据包会导致网络性能变差,丢包次数增大。
- 它没对数据包大小做控制。为了避免IP层对数据包进行分片,应用层应该要保证每个数据包的大小不超过MTU。如果这个数据包会经过广域网(一般情况下)这个值应该不超过576。考虑到IP头的20字节,udp头的8个字节,以及这个协议头的字节。最好每次发送的数据大小在512以内。
这个协议这么简陋,那要它何用?
首先,对于互相独立的数据包,没有必要保证包的有序性。以游戏开发为例子,玩家在客户端发起一个开宝箱请求的同时,又迅速的切换界面,打开了角色面板又发起一个查看角色数据的请求。保证这两个请求的先后顺序真的有意义吗?
其次,对于大部分的小数据包,没有必要考虑IP分片。玩家发起一个开宝箱的请求,可能整个数据包的内容就是一个请求id和一个宝箱id。假设这两个id都是64位,也就是16字节,整个IP包的大小并不足以让IP层进行分片处理。如果你的系统绝大部分都是这种小包,或许你能不考虑IP分片。
再来谈谈tcp的字节流服务。正如大家所知道的,tcp是提供可靠的字节流服务的。但是,一般情况下我们真的需要传输层提供这种服务吗?以游戏服务器为例子,在用tcp与客户端进行网络通讯上,我们现在的做法是在字节流上对请求、响应进行封包解包,也就是在字节流之上,模拟一个数据包的传输。并且我相信很多其它游戏也是这么做的。数据在IP层上本来就是通过包的形式进行传输,tcp对此做了抽象实现了字节流,应用层又在字节流之上模拟出数据包。是否可以用udp去减少这些不必要的抽象呢?或许我们仅需要的是一个有序可靠的数据包服务,又或许我们连有序性都不需要。。。
总结
最后,我想说的是并没有一套解决方案能适用与所有情况。tcp作为传输层给出的是一套通用性的解决方案,并致力于满足大多数的需求,但是总会有其不适合的地方。这个时候我们就可以使用udp来自己定制一套时候自己业务的协议。这套协议不一定是很复杂,其实实现一个可靠的udp也并不是很复杂,关键要看你需要协议提供什么功能!
参考资料
- 可靠UDP传输。地址:http://blog.codingnow.com/2016/03/reliable_udp.html
- KCP。地址:https://github.com/skywind3000/kcp
可靠UDP的更多相关文章
- Unity跨平台C/CPP动态库编译---可靠UDP网络库kcp基于CMake的各平台构建实践
1.为什么需要动态库 a)提供原生代码(native code)的支持,也叫原生插件,但是我实践的是c/cpp跨平台动态库,这里不具体涉及安卓平台java库和ios平台的objectc库构建. b)某 ...
- TCP与UDP,可靠UDP如何实现
两种协议都是传输层协议,为应用层提供信息载体. TCP协议是基于连接的字节流的可靠协议,有三次握手,四次挥手,超时重传,流量控制(滑动窗口),拥塞控制和差错控制,也正因为有可靠性的保证和控制手段,所以 ...
- 可靠UDP设计
最近加入了一个用帧同步的项目,帧同步方案对网络有着极大的影响,于是采用了RUDP(可靠UDP),那么为什么要摒弃TCP,而费尽心思去采用UDP呢?要搞明白这个问题,首先要了解TCP和UDP的区别 , ...
- 开源基于asio的网络通信框架asio2,支持TCP,UDP,HTTP,RPC,SSL,跨平台,支持可靠UDP,支持TCP自动拆包,TCP数据报模式等
开源基于asio的网络通信框架asio2,支持TCP,UDP,HTTP,RPC,SSL,跨平台,支持可靠UDP,支持TCP自动拆包,TCP数据报模式等 C++开发网络通信程序时用asio是个不错的选择 ...
- 可靠UDP,KCP协议快在哪?
WeTest 导读 云真机已经支持手机端的画面投影.云真机实时操作,对延迟的要求比远程视频对话的要求更高(100ms以内).在无线网络下,如何更实时.更可靠的传输视频流就成了一个挑战.通过websoc ...
- 云风的BLOG❳可靠 UDP 传输
http://mp.weixin.qq.com/s?__biz=MzA3NjYxOTA0MQ==&mid=405432715&idx=1&sn=2e40ceafd4b298e1 ...
- UDP可靠传输那些事
有空来论坛走走,发现讨论udp可靠传输又热了起来,有人认为udp高效率,有人认为udp丢包重传机制容易控制,还有朋友搞极限测试,当然也有人推销自己的东西,这里写一点我个人的看法. udp可靠传输其实非 ...
- UDP如何实现可靠传输
概述 UDP不属于连接协议,具有资源消耗少,处理速度快的优点,所以通常音频,视频和普通数据在传送时,使用UDP较多,因为即使丢失少量的包,也不会对接受结果产生较大的影响. 传输层无法保证数据的可靠传输 ...
- 【Network】高性能 UDP 服务应该怎么搞?
参考资料: Netty系列之Netty高性能之道 C++高性能服务框架revover:rudp总体介绍(可靠UDP传输) - zerok的专栏 - 博客频道 - CSDN.NET 高性能异步Socke ...
随机推荐
- CDC的StretchBlt函数载入位图时图片失真问题
最近遇到加载的bmp图片出现失真问题,查找得知需要用SetStretchBltMode函数设置拉伸模式. 函数原型:int SetSTretchBltMode(HDC hdc, int iStretc ...
- 使用geoserver发布arcgis切片
arcgis map 版本:10.1,10.2,10.3均可 jre:7或者8 geoserver:2.8.2以上 切片:松散型,256*256 ,png 1:安装geoserver并独立部署geo ...
- struts 国际化
国际化 1. 国际化与本地化 国际化 (Internationalization: I18N): 是程序在不做任何修改的情况下,就可以再不同的国家或地区和不同的语言环境下,按照当地的语言和格式习惯显示 ...
- 七牛整合php上传从微信下载接口下载下来的文件
因为ios系统直接读取不了MP3格式的文件,所以从微信接口下载下来的MP3格式音频上传到七牛后要转码. Sample code: public function doMobileUploadT ...
- gerrit add review标签
添加verifyed标签 http://blog.csdn.net/terence427/article/details/16840697
- Mysql索引的类型和优缺点
索引是一种特殊的文件(InnoDB数据表上的索引是表空间的一个组成部分),它们包含着对数据表里所有记录的引用指针.注:[1]索引不是万能的!索引可以加快数据检索操作,但会使数据修改操作变慢.每修改数据 ...
- JavaScript中正则表达式test()、exec()、match() 方法
转自http://www.cnblogs.com/jane-y/articles/5183859.html 1.test test 返回 Boolean,查找对应的字符串中是否存在模式.var str ...
- 用hexdump获取event的输出信息
当我们在调试输入设备时,如:键盘,触摸屏 会使用到hexdump工具.其内容如下: 1. 键盘: # cat /dev/input/event0 | hexdump 0000000 f6a6 4e15 ...
- sql数据库不能用localhost/phpMyadmin登陆,真正要修改的文件是哪个
今天,数据库抽风,在地址栏输入localhost/phpmyadmin尽然显示没有访问权限的英文....查了资料都是有好多解决方案,基本都是先点击绿色的w图标,然后找到apache下的httpd.co ...
- Android的学习第六章(布局一TableLayout)
今天我们来简单的说一下Android不居中的TableLayout布局(表格布局) 表格布局的意思就是将我们的布局看做为一个表格,主要用于对控件进行整齐排列 我们看一个简单的案例 <TableL ...