发送至特定远程 IP 的第一个 UDP 消息丢失

2023-11-24

我正在开发一个基于 LAN 的解决方案,其中一个“服务器”必须控制多个“玩家” 我选择的协议是 UDP,因为它很简单,我不需要连接,我的流量仅由时不时的短命令组成,我想使用混合广播消息进行同步,并使用单个目标消息进行玩家单独的命令。

多播 TCP 是一种替代方案,但它更复杂,不完全适合该任务,并且通常得不到硬件的良好支持。

不幸的是我遇到了一个奇怪的问题:

使用“sendto”发送到特定 IP 的第一个数据报丢失。稍后发送到同一 IP 的任何数据报都会被接收。 但如果我等待一段时间(几分钟),第一个“sendto”就会再次丢失。

广播数据报始终有效。 本地发送(到同一台计算机)始终有效。

我推测操作系统或路由器/交换机有一些从 IP 到 MAC 地址的转换表,在几分钟不使用时会被遗忘,不幸的是会导致数据报丢失。 我可以用不同的路由器/交换机硬件观察到这种行为,所以我怀疑是 Windows 网络层。

我知道 UDP 根据定义是“不可靠的”,但我无法相信这种情况会发展到即使物理连接正常工作并且一切都定义良好的数据包也可能丢失。那么它就真的毫无价值了。

从技术上讲,我正在打开一个 UDP 套接字, 将其绑定到端口和 INADRR_ANY。 然后我使用“sendto”和“recvfrom”。 我从不进行连接——我不想这样做,因为我有几个玩家。据我所知,UDP 应该在没有连接的情况下工作。

我当前的解决方法是定期向所有特定玩家 ip 发送虚拟数据报 - 这解决了问题,但在某种程度上“不令人满意”

问题:有人知道这个问题吗?它从何而来?我该如何解决?

Edit:

我将其归结为以下测试程序:

int _tmain(int argc, _TCHAR* argv[])
{
    WSADATA wsaData;
    WSAStartup(MAKEWORD(2, 2), &wsaData);
    SOCKET Sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    SOCKADDR_IN Local = {0};
    Local.sin_family = AF_INET;
    Local.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
    Local.sin_port = htons(1234);
    bind(Sock, (SOCKADDR*)&Local, sizeof(Local));
    printf("Press any key to send...\n");
    int Ret, i = 0;
    char Buf[4096];

    SOCKADDR_IN Remote = {0};
    Remote.sin_family = AF_INET;
    Remote.sin_addr.S_un.S_addr = inet_addr("192.168.1.12");  // Replace this with a valid LAN IP which is not the hosts one
    Remote.sin_port = htons(1235);

    while(true) {
        _getch();
        sprintf(Buf, "ping %d", ++i);
        printf("Multiple sending \"%s\"\n", Buf);

        // Ret = connect(Sock, (SOCKADDR*)&Remote, sizeof(Remote));
        // if (Ret == SOCKET_ERROR) printf("Connect Error!\n", Buf);
        Ret = sendto(Sock, Buf, strlen(Buf), 0, (SOCKADDR*)&Remote, sizeof(Remote));
        if (Ret != strlen(Buf)) printf("Send Error!\n", Buf);
        Ret = sendto(Sock, Buf, strlen(Buf), 0, (SOCKADDR*)&Remote, sizeof(Remote));
        if (Ret != strlen(Buf)) printf("Send Error!\n", Buf);
        Ret = sendto(Sock, Buf, strlen(Buf), 0, (SOCKADDR*)&Remote, sizeof(Remote));
        if (Ret != strlen(Buf)) printf("Send Error!\n", Buf);
        }
    return 0;

该程序打开一个 UDP 套接字,并在每次击键时连续发送 3 个数据报到特定 IP。 运行whithwireshark观察你的UDP流量,按下一个键,等待一段时间,然后再次按下一个键。 您不需要远程 IP 上的接收器,这没有什么区别,除非您不会收到黑色标记的“无法到达”数据包。 这就是你得到的:

Wireshark Snapshot

正如您所看到的,第一次发送启动了 IP 的 ARP 搜索。当搜索等待时,连续 3 次发送中的前 2 次丢失。 第二次击键(IP 搜索完成后)正确发送了 3 条消息。 您现在可以重复发送消息,它会一直工作,直到您等待(大约一分钟,直到地址翻译再次丢失),然后您将再次看到丢失。

这意味着:发送 UDP 消息时没有发送缓冲区,并且有 ARP 请求待处理!除最后一条消息外,所有消息都会丢失。 另外“sendto”在发送成功之前不会阻塞,并且不会有错误返回!

好吧,这让我感到惊讶,也让我有点难过,因为这意味着我必须接受当前的解决方法,或者实现一个 ACK​​ 系统,一次只发送一条消息,然后等待回复 - 这对任何人来说都不容易更多,意味着许多困难。


我在其他人回答之后很久才发布这个帖子,但它是直接相关的。

如果没有目标地址(或目标网关)的 ARP 条目,Winsock 将丢弃 UDP 数据包。

因此,很可能第一个 UDP 数据包的某些数据包会被丢弃,因为此时没有 ARP 条目 - 并且与大多数其他操作系统不同,winsock 在 ARP 请求完成时仅排队 1 个数据包。

这是有记录的here:

ARP 仅对指定目的地的一个出站 IP 数据报进行排队 地址,同时将该 IP 地址解析为 MAC 地址。如果一个 基于 UDP 的应用程序将多个 IP 数据报发送到单个 目标地址之间没有任何停顿,一些 如果还没有 ARP 缓存条目,数据报可能会被丢弃 展示。应用程序可以通过调用来补偿这一点 Iphlpapi.dll例程SendArp()建立一个ARP缓存条目,之前 发送数据包流。

可以在以下位置观察到相同的行为Mac OS X and FreeBSD:

当接口请求地址映射时, 在缓存中,ARP 将需要的消息排队 映射并在关联的关联上广播消息 网络请求地址映射。如果响应是 如果新的映射被缓存并且任何待处理的消息被缓存 传送。 ARP 在等待时最多排队一个数据包 用于响应映射请求;仅最近的 保留“已传输”数据包。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

发送至特定远程 IP 的第一个 UDP 消息丢失 的相关文章

  • 每个托管线程是否都有自己对应的本机线程?

    我想知道是否在 Net 中创建托管线程 通过调用Thread Start 导致在后台创建一个本机线程 那么托管线程是否有对应的本机线程呢 如果是 当托管线程等待或睡眠时 是否意味着相应的本机线程也在等待或睡眠 是的 NET 线程映射到所有当
  • 如何在c++中读取pcap文件来获取数据包信息?

    我想用 C 编写一个程序来读取 pcap 文件并获取数据包的信息 例如 len sourc ip flags 等 现在我找到了如下代码 我认为它会帮助我获取信息 但是我有一些疑问 首先我想知道应该将哪个库添加到我的程序中 然后什么是 pca
  • 如何让 Swagger 插件在自托管服务堆栈中工作

    我已经用 github 上提供的示例重新提出了这个问题 并为任何想要自己运行代码的人提供了一个下拉框下载链接 Swagger 无法在自托管 ServiceStack 服务上工作 https stackoverflow com questio
  • 计算 Richtextbox 中所有单词的最有效方法是什么?

    我正在编写一个文本编辑器 需要提供实时字数统计 现在我正在使用这个扩展方法 public static int WordCount this string s s s TrimEnd if String IsNullOrEmpty s re
  • MVC 在布局代码之前执行视图代码并破坏我的脚本顺序

    我正在尝试将所有 javascript 包含内容移至页面底部 我正在将 MVC 与 Razor 一起使用 我编写了一个辅助方法来注册脚本 它按注册顺序保留脚本 并排除重复的内容 Html RegisterScript scripts som
  • 复制 std::function 的成本有多高?

    While std function是可移动的 但在某些情况下不可能或不方便 复制它会受到重大处罚吗 它是否可能取决于捕获变量的大小 如果它是使用 lambda 表达式创建的 它依赖于实现吗 std function通常被实现为值语义 小缓
  • C中的malloc内存分配方案

    我在 C 中尝试使用 malloc 发现 malloc 在分配了一些内存后浪费了一些空间 下面是我用来测试 malloc 的一段代码 include
  • 使用 LINQ2SQL 在 ASP.NET MVC 中的各种模型存储库之间共享数据上下文

    我的应用程序中有 2 个存储库 每个存储库都有自己的数据上下文对象 最终结果是我尝试将从一个存储库检索到的对象附加到从另一个存储库检索到的对象 这会导致异常 Use 构造函数注入将 DataContext 注入每个存储库 public cl
  • 使用接口有什么好处?

    使用接口有什么用 我听说它用来代替多重继承 并且还可以用它来完成数据隐藏 还有其他优点吗 哪些地方使用了接口 程序员如何识别需要该接口 有什么区别explicit interface implementation and implicit
  • 如何使用 LINQ2SQL 连接两个不同上下文的表?

    我的应用程序中有 2 个数据上下文 不同的数据库 并且需要能够通过上下文 B 中的表的右连接来查询上下文 A 中的表 我该如何在 LINQ2SQL 中执行此操作 Why 我们正在使用 SaaS 产品来跟踪我们的时间 项目等 并希望向该产品发
  • 由 IHttpClientFactory 注入时模拟 HttpClient 处理程序

    我创建了一个自定义库 它会自动为依赖于特定服务的 Polly 策略设置HttpClient 这是使用以下方法完成的IServiceCollection扩展方法和类型化客户端方法 一个简化的例子 public static IHttpClie
  • qdbusxml2cpp 未知类型

    在使用 qdbusxml2cpp 程序将以下 xml 转换为 Qt 类时 我收到此错误 qdbusxml2cpp c ObjectManager a ObjectManager ObjectManager cpp xml object ma
  • C#:帮助理解 UML 类图中的 <>

    我目前正在做一个项目 我们必须从 UML 图编写代码 我了解 UML 类图的剖析 但我无法理解什么 lt
  • C# 中的合并运算符?

    我想我记得看到过类似的东西 三元运算符 http msdn microsoft com en us library ty67wk28 28VS 80 29 aspx在 C 中 它只有两部分 如果变量值不为空 则返回变量值 如果为空 则返回默
  • “接口”类似于 boost::bind 的语义

    我希望能够将 Java 的接口语义与 C 结合起来 起初 我用过boost signal为给定事件回调显式注册的成员函数 这非常有效 但后来我发现一些函数回调池是相关的 因此将它们抽象出来并立即注册所有实例的相关回调是有意义的 但我了解到的
  • 将 MQTTNet 服务器与 MQTT.js 客户端结合使用

    我已经启动了一个 MQTT 服务器 就像this https github com chkr1011 MQTTnet tree master例子 该代码托管在 ASP Net Core 2 0 应用程序中 但我尝试过控制台应用程序 但没有成
  • 不同类型指针之间的减法[重复]

    这个问题在这里已经有答案了 我试图找到两个变量之间的内存距离 具体来说 我需要找到 char 数组和 int 之间的距离 char data 5 int a 0 printf p n p n data 5 a long int distan
  • 方法优化 - C#

    我开发了一种方法 允许我通过参数传入表 字符串 列数组 字符串 和值数组 对象 然后使用这些参数创建参数化查询 虽然它工作得很好 但代码的长度以及多个 for 循环散发出一种代码味道 特别是我觉得我用来在列和值之间插入逗号的方法可以用不同的
  • C++ 条件编译

    我有以下代码片段 ifdef DO LOG define log p record p else define log p endif void record char data 现在如果我打电话log hello world 在我的代码中
  • 当我使用 OpenSSL1.1.0g 根据固定的 p 和 g 值创建 Diffie Hellman 密钥协议密钥时,应该执行哪些检查?

    您好 我尝试通过这段代码使用修复 p 和 g 参数来制作 Diffie Hellman Keysanswer https stackoverflow com a 54538811 4706711 include

随机推荐

  • 似乎正在等待的线程的 CPU 利用率很高

    我目前正在运行一些 JMeter 测试来测试 Web 服务的性能 它使用了大量的 CPU 对于一个 JMeter 请求线程 其使用率为 10 30 取决于请求的类型 当我将其增加到仅 15 个线程时 CPU 利用率约为 95 自然 我想弄清
  • 演示正在进行时在场吗?尝试在 facebook 登录后使用解析显示新视图。

    我试图呈现一个我已经为用户输入数据并保存在解析中的 UITableView 我很确定我没有呈现导航视图 当我登录时 我收到错误 Checklists 4516 c07 Warning Attempt to present
  • Android SQLite 在复杂查询中的性能

    假设我有这样的查询 String sql SELECT s team id s team name s gp s w s t s l s go s ga s score s p FROM SELECT team id team name S
  • Google Maps API V3 - 无论如何要检索自动完成结果而不是下拉渲染吗?

    我需要渲染结果google maps places Autocomplete以自定义方式 而不是默认的下拉菜单 有什么方法可以使用 Google Maps API V3 检索自动完成的相同信息 但在每个请求的数组中而不是 API 为我进行渲
  • 检查本地存储是否可用

    我知道有很多关于检查的问题localStorage但如果有人在浏览器中手动关闭它怎么办 这是我用来检查的代码 localStorage setItem mod mod if localStorage getItem mod null ale
  • 活动被销毁是因为方向改变还是因为应用程序正在关闭?

    我有一个Activity启动一个异步任务 允许以纵向或横向方向显示活动 当方向改变时 Activity 将被销毁并重新创建 无论方向改变多少次 任务都会继续工作 它还成功地将结果返回给活动 根据 CommonsWare 的回答 http g
  • 如何使用 Selenium WebDriver C# 从下拉列表中选择一个选项?

    我正在尝试选择一个选项进行网络测试 可以在这里找到一个例子 http www tizag com phpT examples formex php 除了选择一个选项部分之外 一切都很好 如何按值或按标签选择选项 My Code using
  • 如何将 selenium chrome 选项添加到“desiredCapability”?

    对于 selenium 我有很多 chrome 选项 我需要通过以下方式将其传递给远程网络驱动程序DesiredCapabilities 在本页有一个关于如何执行此操作的 java 示例 但是如何在 python 中执行此操作 这文档很穷
  • 使用 CNN 处理一维数据

    只是想知道是否有人这样做过 我有一个一维的数据集 但不确定它是否是正确的单词选择 与通常的 CNN 输入图像 二维 不同 我的数据只有一维 一个例子是 instance1 feature1 feature2 featureN instanc
  • Python ctypes 未在 Mac OS X 上加载动态库

    我有一个 C 库repeater so我可以通过以下方式从 Linux 中的 Python 加载 import numpy as np repeater np ctypeslib load library librepeater so 但是
  • 使用 GCC 的链接器错误,包括。用于 binutils 和 textinfo

    我每次在编译程序 配置和安装一些东西时都会收到此错误 例如binutils 文本信息等 usr local bin ld this linker was not configured to use sysroots collect2 err
  • 使用 Apple Pay 创建令牌,无需付款

    我有两个问题 有没有办法使用 Apple Pay 创建 STPToken 而无需付款 在我的 iOS 应用程序中 客户在注册时要么输入付款信息 要么决定使用 Apple Pay 当客户决定购买时 注册后的某个时间 他们的卡将自动扣款 我可以
  • Kdevelop 步骤和断点不起作用

    我需要使用步骤 单步执行 单步执行指令 和断点 但选项 跳过 跳过指令 等 在菜单 运行 中被禁用 当我在程序中放置断点时 程序不会在此断点处停止 我发现我必须关闭编译器和链接器的优化 但我不知道如何关闭 Kdevelop 4 4 1 中的
  • ASP.NET:视图状态和以编程方式添加用户控件

    当使用 LoadControl string path 以编程方式添加用户控件时 在用户控件的页面生命周期中 它何时使用其视图状态初始化其子控件 我问这个问题是因为我正在以编程方式加载的用户控件之一有一个 TextBox 控件 该控件未通过
  • 使用批处理文件命名驱动器

    我正在寻找一个命令来重命名我在 WinXP 中每次启动时映射的几个驱动器 我已经完成了映射部分 现在我有兴趣使用自定义名称以编程方式命名它们 这样我就可以保持它们的一致性 我放弃了 DOS 转而学习 PowerShell 最终的结果是这样的
  • Node.js“require”语句中的大括号(大括号)

    我试图理解下面两个 require 语句之间的区别 具体来说 其目的是什么 s 缠绕着ipcMain const electron require electron const ipcMain require electron 他们似乎都分
  • 如何在 Android 中缩放文本视图?

    谁能指导我在android中的多个视图上执行放大和缩小操作 我需要在图像 文本视图的触摸上执行放大和缩小操作 我的父级布局应该是什么 这是在触摸图像视图时缩放图像的代码 如何缩放文本视图 请帮我 These matrices will be
  • 所有 OLE 错误代码的列表

    是否有所有 OLE 错误代码的列表 None
  • 如何跟踪 WCF 序列化问题/异常

    我偶尔会遇到这样的问题 在 WCF 序列化期间 从我的 OperationContract 返回 DataContract 后 抛出应用程序异常 我收到的唯一 且意义不大 的消息是 System ServiceModel Communica
  • 发送至特定远程 IP 的第一个 UDP 消息丢失

    我正在开发一个基于 LAN 的解决方案 其中一个 服务器 必须控制多个 玩家 我选择的协议是 UDP 因为它很简单 我不需要连接 我的流量仅由时不时的短命令组成 我想使用混合广播消息进行同步 并使用单个目标消息进行玩家单独的命令 多播 TC