【Network】UDP 大包怎么发? MTU怎么设置?
这里主要用UDP来发送视频,当发送的数据大于1500时分包发送,保证每包小于1500.
发送好办,分割后循环发就可以了,关键是接收时的处理。
先做一下处理的方法 :
发送时每包上面加上标识,比如RTP的做法是加时间戳,SSRC,媒体类型还有结束标识。简单参考一下,我们也加上一些标识(直接拿RTP头也可以, 不过我们的目标是更简洁一些)。另外,我们的目的和RTP稍有不同,UDP库当时设计是传输数据,而不关心数据的内容是什么。这样,简单一化,包头第一个INT定义为类型,第二个INT为序号,第三个为结束标志,之后是数据长度和数据内容。
代码演示:
int CUDPSession::SplitData(char* pBuff, uint32_t nLen)
{
int nBlockNum = nLen / UDP_BLOCK_SIZE;
if (nLen % UDP_BLOCK_SIZE != 0)
{
nBlockNum++;
}
int sendlen = 0;
for (int i = 0; i < nBlockNum; i++)
{
int poayload_size = UDP_BLOCK_SIZE;
char* payload = pBuff + UDP_BLOCK_SIZE * (i);
if (nLen - UDP_BLOCK_SIZE * (i) < UDP_BLOCK_SIZE)
poayload_size = nLen - UDP_BLOCK_SIZE * (i);
CPackOut* pack = new CPackOut;
(*pack) << PACK_TYPE_DATA;
(*pack) << m_nFrameIndex;
if (i == nBlockNum - 1)
{
(*pack) << 1;
}
else
{
(*pack) << 0;
}
(*pack) << poayload_size;
(*pack).SetBuffer(payload, poayload_size);
int ret = SendPacket(pack, m_destIP, m_destPort);
printf("SendPacket ret = %d\n", ret);
sendlen += ret;
delete pack;
pack = NULL;
}
return sendlen;
}
发送端就这么简单。
下面详细说一下接收端:
因为UDP是不可靠的,不保证数据帧一定正常到达,即使收到,顺序也可能发生变化,比如先发的后到,当然丢包的可能最大,乱序的情况比较少。
正常的处理方法一般这样:
假设一个端口只接收固定一个对方数据源,这样,收到一个数据包放到缓冲里,然后在缓冲里根据帧的序号排序(每一帧的大序号是相同的,自己可以给每一个小片加上小序号,包头里可以加上本次数据帧一共分多少片,收到一片就统计一下,判断是否收齐)。 当收齐后,这个帧去掉包头回调给上层。当在一定时间内该帧数据还没有收齐,就说明传输过程有丢包了,把已收到的都丢掉就可以。
当上层的应该收到回调的数据后,可以进行解码播放。不过在解码之前,先判断一下帧序列是否连续。做为视频数据,
如果中间有缺少的,就把这一序列都丢掉,直到下一个I帧。每个帧的序号,最好收发之间协商好,在发送的时候带上。
如果把上面整个过程都实现,完全自己写的话,是需要几天的时间。不过,从很多RTP开源库里发现,处理的都非常简单,很多都没有管乱序情况,简单地来一份数据就向缓冲里追加一份,直到发现mark为1。我们这里做为简单使用的项目,也采用了这种简单方法,先把功能完成,之后有时间再来优化。
简单的重组代码:
int CUDPSession::Reassemble(CPackIn& pack, uint32_t ip, uint32_t port)
{
int nSeq = 0;
int nMark = 0;
int nLen = 0;
pack >> nSeq;
pack >> nMark;
pack >> nLen;
if (m_nRecvFrameIndex != nSeq)
{
if (m_buffer)
{
evbuffer_free(m_buffer);
m_buffer = NULL;
}
m_nRecvFrameIndex = nSeq;
}
if (m_buffer == NULL)
{
m_buffer = evbuffer_new();
}
char* pBuf = 0;
int nSize;
pack.GetBuffer(pBuf, nSize);
evbuffer_add(m_buffer, pBuf, nSize);
if (nMark == 1)
{
//回调
if (m_pCB)
{
m_pCB(m_udpIO.m_handle, (char*)(m_buffer->buffer), m_buffer->off, ip, port,
m_pParam);
}
evbuffer_free(m_buffer);
m_buffer = NULL;
}
return 0;
}
程序里使用的evbuffer,是从libevent里面拿来的,主要用来处理数据缓冲,非常好用,效率也很好,见evbuffer.h和buffer.cpp。
完整代码在git上,这次实现的功能是:本机UDP bind5500端口-->摄像机采集-->编码-->发送给本机的5500端口-->收到后再解码--> 显示。
发送的代码:m_Sess.Send((char*)pData, nLen, inet_addr("127.0.0.1"), 5500);
这个程序可以分别运行在两台机器上,一台是发送,另一台是接收。发送方只要把上面这一句里面的127.0.0.1换上你目标的ip,另一台机器就可以接收并解码了。
本文结束后,完整的客户端功能基本就差不多了,下一步开始完成server端的stun, 协商穿透, 实p2p和中转视频。
另补充一下,如果发送的是int类型的数据,一般应该用htonl,htons和ntohl,ntohs转换一下。这里的代码暂时没有用,以后会完善的。如果自己写代码应该注意。
https://github.com/sxcong/rttim
参考资料
- java - Which is the best approach to send large UDP packets in sequence - Stack Overflow
- networking - sending a big file in UDP in C - Stack Overflow
- sockets - is it possible to send very big data over UDP? - Stack Overflow
- c - How to send UDP packets of size greater than 64 KB - Stack Overflow
- udp - How to send large data using C# UdpClient? - Stack Overflow
- sockets - Python: Sending large object over UDP - Stack Overflow
- UDP and packets greater than 1500 bytes
- UDP and packets larger than 1500 bytes / Networking, Server, and Protection / Arch Linux Forums
- UDP主要丢包原因及具体问题分析
- UDP需要自己分包么 - C/C++-ChinaUnix.net
- 音视频聊天开发: 5 UDP发送视频数据的分包和重组 -sxcong-ChinaUnix博客
- Neutron 理解 (3): Open vSwitch + GRE/VxLAN 组网 - 极客头条 - CSDN.NET
- TCP/IP具体解释--TCP/UDP优化设置总结& MTU的相关介绍 - yxwkaifa - 博客园
【Network】UDP 大包怎么发? MTU怎么设置?的更多相关文章
- 路由器mtu值设置
MTU=最大传输单元 单位:字节 英文:Maximum Transmission Unit”我们平时上网时的各种操作,都是通过一个又一个“数据包”传输来实现的.而MTU指定了网络中可传输数据包的最大尺 ...
- 备忘:有MTU值设置不当导致的部分网站无法访问问题
如题,有时候突然weibo.com,webQQ等网站网络连接超时,怎么找也没得原因,今天管理电信的光猫,发现设置的MTU的1400,突然想起之前电脑和路由器上设置的MTU是1500,感觉可能是这个问题 ...
- FreeSWITCH小结:关于sip的UDP、TCP与MTU
1.关于SIP的UDP与MTU的关系 如果sip消息的大小超过了MTU,则有可能被网络中的某一节点分片,而UDP处理分片会有很大的问题,从而导致sip消息传输失败.要解决该问题的话,两种方案: 1)减 ...
- Network | UDP checksum
1. 校验和 ICMP,IP,UDP,TCP报头部分都有checksum(检验和)字段.IP 首部里的校验和只校验首部:ICMP.IGMP.TCP和UDP首部中的校验和校验首部和数据. UDP和TCP ...
- Linux 使用第三方邮箱发邮件的设置
mail命令在Ubuntu下是需要安装的,使用下条命令进行安装: sudo apt-get install heirloom-mailx 在CentOS 下安装则是: yum install mail ...
- SAP 采购订单行项目中科目分配被隐藏,发现行项目设置中显示字段长度为0
1.sm30 维护 视图 TCVIEW 修改对应字段的显示长度
- TCP/IP具体解释--TCP/UDP优化设置总结& MTU的相关介绍
首先要看TCP/IP协议,涉及到四层:链路层,网络层.传输层,应用层. 当中以太网(Ethernet)的数据帧在链路层 IP包在网络层 TCP或UDP包在传输层 TCP或UDP中的数据(Data)在应 ...
- [转帖]关于网络编程中MTU、TCP、UDP优化配置的一些总结
关于网络编程中MTU.TCP.UDP优化配置的一些总结 https://www.cnblogs.com/maowang1991/archive/2013/04/15/3022955.html 感谢原作 ...
- NB-IOT使用LWM2M移动onenet对接之MTU最大传输单元设置
1. 最近遇到的一个项目NB-IOT使用LWM2M移动onenet对接,要求设置传输的MTU,因此首先需要搞懂MTU是什么? 以太网的MTU值是1500 bytes,假设发送者的协议高层向IP层发送了 ...
随机推荐
- JS组件系列——Bootstrap寒冬暖身篇:弹出框和提示框效果以及代码展示
前言:对于Web开发人员,弹出框和提示框的使用肯定不会陌生,比如常见的表格新增和编辑功能,一般常见的主要有两种处理方式:行内编辑和弹出框编辑.在增加用户体验方面,弹出框和提示框起着重要的作用,如果你的 ...
- 读书笔记---《火球:UML大战需求分析》
书评 作为一本UML和需求分析的入门书来说还算可以,写的比较接地气,如果是做过很多项目的读者,很容易找到共鸣点. 美中不足:部分概念可能有错误,其中对于Component和Artifact的解释明显和 ...
- 【转】js实现复制到剪贴板功能,兼容所有浏览器
两天前听了一个H5的分享,会议上有一句话,非常有感触:不是你不能,而是你对自己的要求太低.很简单的一句话,相信很多事情不是大家做不到,真的是对自己的要求太低,如果对自己要求多一点,那么你取得的进步可能 ...
- Mysql连表之多对多
说明 这里的文章是接着前面 Mysql连表一对多 写的. 连表多对多 可以理解成一夫多妻和一妻多夫. 男人表: nid name 1 xxx 2 yyy 3 zzz 女人表: nid name 1 a ...
- qthread 使用 signal 方法通信
因为之间尝试过的 signal 机制,都是在 emit singnal_my() 的地方,直接调用了 slot 函数:相当于,slot 只是一个回调函数. 所以,在这里有点困惑,如果是要顺序执行完 s ...
- NGUI 滑动特效之中间放大滚动
效果图如下: 其实很简单,在NGUI原有的滑动组件的基础上处理一下比例系数就好,每个块的位置是固定的,移动的是Panel. 所以呢用Panel的位置与块的位置做差在比几个块不就成了比例系数了么..自然 ...
- NGUI 滑动与点击事件冲突处理
弄一个既能滑动,又能点击的Scroll View.发现弄完后不能拖动了~ 因为点击事件需要Box Collider覆盖掉了Drag Scroll View的Box Collider.注意是Drag S ...
- 配置linux----------------ip
在终端中输入 vi /etc/sysconfig/network-scripts/ifcfg-eth0 =================================== DEVICE=" ...
- K米点歌APP评测
K米APP评测 产品简介 K米点歌是一款免费的社交K歌手机应用,其手机点歌功能主要在KTV.夜总会,酒吧等K歌场所中使用,当前提供iPhone版本及安卓版本下载使用.——百度百科 评测版本 K米点歌4 ...
- 09 Object
Object 在看 ES6 Object的时候,我发觉ES5 Object 的更新我并不是完全知道. 于是觉得还是看一下. 1. __proto__ 作为一个 半吊子前端开发人员. 居然不知道这个.. ...