c# - C ++中的UDP帧丢失
问题描述
我有一个 C# 代码,它从 UDP 获取数据并计算丢失的帧(如果有)。它工作正常。我用 C++ 编写了相同的代码,看看我是否比 C# 代码更快地获取数据。
但是,在进行比较之前,我遇到了问题;在 C++ 代码中,我丢失了很多帧。
在这两个代码中;我将部分数据解析为用户创建的标题。一帧由 7 个片段组成。FrameFragmentNo
按顺序计算段。在 C# 代码中它计数为 1,2,3..7 但在 C++ 中它从 5 等开始并计数为 5,6 然后新帧出现 1,6 等。这意味着 C++ 代码永远不会正确地获取帧。(C# 代码丢失框架自然但很少见)TotalFragmentCount
对两者都是正确的。
safe_increment
是在计算框架的碎片时,在顺序被破坏时计算一次。不要介意intData
这是关于其余数据的一些过程。
有趣的是,当我跟踪 C++ 代码时,有时它的计数是正确的。我怀疑 Windows 操作系统的缓冲区大小,但如果是这种情况,C# 代码应该不能正常工作。我检查了其他帖子,大多数人问包裹丢失,但是我有一个框架丢失。我还想,也许我拍帧太快了,但它无法提出解决方案。
有人对这种行为有什么建议吗?
这是 C# 代码工作正常,按顺序计算帧片段
private void ReceiveData()
{
byte[] content;
UInt16[] intData = new UInt16[0] { };
UInt16 SkipFrameFlag = 1;
dataReceiveThreadStarted = true;
while (true)
{
content = udpClientData.Receive(ref IPEndPointDataReceiveInformation);//C# skips UDP header
if (!DataReceiveEnabled)
{
continue;
}
//-------------------Parse User Created Header---------------------------
MessageID = (UInt16)(content[0] << 8 | content[1]);
FrameCount = (UInt32)(content[2] << 24 | content[3] << 16 | content[4] << 8 | content[5] << 0);
TotalFragmentCount = (UInt16)(content[6] << 8 | content[7]);
FrameFragmentNo = (UInt16)(content[8] << 8 | content[9]);
Reserved = (UInt16)(content[10] << 8 | content[11]);
MessageLength = (UInt16)(content[12] << 8 | content[13]);
if (FrameFragmentNo == 1 && SkipFrameFlag == 1) // After the skip flag, catch the start of frame.
{
SkipFrameFlag = 0;
PrevFrameFragmentNo = 0;
safe_increment = true;
Array.Clear(intData, 0, intData.Length);
}
//Fragment is lost. Skip Frame
if (FrameFragmentNo != (PrevFrameFragmentNo + 1)) {
SkipFrameFlag = 1;
//increment once when a frame is lost
if (safe_increment)
{
lostFrameCount++;
safe_increment = false;
}
}
if (SkipFrameFlag == 1)
continue;
if (FrameFragmentNo == TotalFragmentCount && intData != null) // Frame Fragmentation Completed
{
ragmentNo = 0;
PrevFrameCount = FrameCount;
ReceivedFrameCount++;
ReceivedFrameLen = intData.Length;
}
}
这是丢失太多帧或花费太快的 C++ 代码我不知道
while (true)
{
ZeroMemory(&client, clientLength); // Clear the client structure
ZeroMemory(buf, 1550); // Clear the receive buffer
// Wait for message
int bytesIn = recvfrom(in, buf, 1550, 0, (sockaddr*)&client, &clientLength);
if (bytesIn == SOCKET_ERROR)
{
cout << "Error receiving from client " << WSAGetLastError() << endl;
continue;
}
//-------------------Parse User Created Header----------------------
MessageID = (uint16_t)(buf[0] << 8 | buf[1]);
FrameCount = (uint32_t)(buf[2] << 24 | buf[3] << 16 | buf[4] << 8 | buf[5] << 0);
TotalFragmentCount = (uint16_t)(buf[6] << 8 | buf[7]);
FrameFragmentNo = (uint16_t)(buf[8] << 8 | buf[9]);
Reserved = (uint16_t)(buf[10] << 8 | buf[11]);
MessageLength = (uint16_t)(buf[12] << 8 | buf[13]);
if (FrameFragmentNo == 1 && SkipFrameFlag == 1) // After the skip flag, catch the start of frame.
{
SkipFrameFlag = 0;
PrevFrameFragmentNo = 0;
safe_increment = true;
intData.clear();
}
if (FrameFragmentNo != (PrevFrameFragmentNo + 1)) //Fragment is lost. Skip Frame
{
SkipFrameFlag = 1;
if (safe_increment) {
lostFrameCount++;
safe_increment = false;
}
}
if (SkipFrameFlag == 1)
continue;
if (FrameFragmentNo == TotalFragmentCount && intData.size() != 0) // Frame Fragmentation Completed
{
PrevFrameFragmentNo = 0;
PrevFrameCount = FrameCount;
ReceivedFrameCount++;
ReceivedFrameLen = intData.size();
}
}
解决方案
推荐阅读
- sql - 在数据库 MVC5 中保存多张图片
- php - Mysql Laravel 复杂查询以求和项目数量
- oracle - 在 sqlplus 中处理未找到的异常
- r - 解析R中数据框列中的json数据
- ios - 如何从 Windows 生成没有 xcode 的 ipa 文件?如果可能的话
- android - RecyclerView 滚动中的 Listview 无法正常工作?
- php - 返回 lastInsertID 时出现“无效的参数号:未绑定任何参数”
- sql-server - 使用 BCP 将文件作为 ANSI 输出为 UTF-8 MSSQL 2012
- microsoft-graph-api - 微软通知网络挂钩
- ios - 如何在 swift 4 中使用 Share Class 过滤 searchController 中的数据