首先UDP消息发送给指定的远程IP丢失 [英] First UDP message to a specific remote ip gets lost

查看:387
本文介绍了首先UDP消息发送给指定的远程IP丢失的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的工作基于LAN解决方案,与具有控制一批运动员服务器
我选择的协议是UDP,因为它很容易,我不需要连接,我的流量仅包括简短的命令不时,我想用广播消息的混合为球员个人的命令同步和单一目标的消息。

I am working on a LAN based solution with a "server" that has to control a number of "players" My protocol of choice is UDP because its easy, I do not need connections, my traffic consists only of short commands from time to time and I want to use a mix of broadcast messages for syncing and single target messages for player individual commands.

组播TCP将是另一种选择,但它比较复杂,不完全适合于任务和由硬件往往不能很好地支持。

Multicast TCP would be an alternative, but its more complicated, not exactly suited for the task and often not well supported by hardware.

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

Unfortunately I am running into a strange problem:

<强>这是使用SENDTO发送到特定IP的第一个数据报丢失。
发送短的时间之后,以相同的IP数据报的任何接收。
但是,如果我等待一段时间(几分钟)的第一个的sendto再次丢失。

The first datagram which is sent to a specific ip using "sendto" is lost. Any datagram sent short time afterwards to the same ip is received. But if i wait some time (a few minutes) the first "sendto" is lost again.

广播数据包总是工作。
本地发送(在同一台计算机)总是工作。

Broadcast datagrams always work. Local sends (to the same computer) always work.

我presume操作系​​统或路由器/交换机具有IP和MAC地址翻译的一些表时不被用于某些分钟,不幸会导致丢失数据包它获取遗忘。
我可以观察到不同的交换机/路由器硬件的行为,所以我怀疑是Windows网络层。

I presume the operating system or the router/switch has some translation table from IP to MAC addresses which gets forgotten when not being used for some minutes and that unfortunately causes datagrams to be lost. I could observe that behaviour with different router/switch hardware, so my suspect is the windows networking layer.

我知道,UDP是定义不可靠,但我不能相信,这正好到目前为止,即使物理连接是否正常工作,一切都被很好地定义数据包可能会丢失。那么这将是从字面上不值钱。

I know that UDP is by definition "unreliable" but I cannot believe that this goes so far that even if the physical connection is working and everything is well defined packets can get lost. Then it would be literally worthless.

从技术上讲,我打开一个UDP套接字,
它绑定到一个端口,INADRR_ANY。
然后,我使用的sendto和recvfrom的。
我永远不会做一个连接 - 我不想因为我有几个球员。据我所知应该UDP连接没有工作。

Technically I am opening an UDP Socket, bind it to a port and INADRR_ANY. Then I am using "sendto" and "recvfrom". I never do a connect - I dont want to because I have several players. As far as I know UDP should work without connect.

我目前的解决办法是,我经常发送无效数据报给所有特定玩家的IPS - 这解决了问题,但不知何故它不能令人满意

My current workaround is that I regularly send dummy datagrams to all specific player ips - that solves the problem but its somehow "unsatisfying"

问:是否有人知道这个问题?这东西从哪里来?我该如何解决呢?

Question: Does anybody know that problem? Where does it come from? How can I solve it?

编辑:

我煮沸它下降到下面的测试程序:

I boiled it down to the following test program:

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套接字,并在每次击键到特定IP连续发送3数据报。
运行蒙山Wireshark的观察你的UDP流量,preSS的关键,再等一会儿preSS的关键。
你并不需要一个接收器上的远程IP,没有什么区别,除了你不会得到黑色标记为不可访问数据包。
这是你会得到什么:

The Program opens an UDP Socket, and sends 3 datagrams in a row on every keystroke to a specific IP. Run that whith wireshark observing your UDP traffic, press a key, wait a while and press a key again. You do not need a receiver on the remote IP, makes no difference, except you wont get the black marked "not reachable" packets. This is what you get:

正如你可以看到发送发起的ARP搜索该IP的第一个。而该搜索被挂起的3连续的第一2发送丢失了。
第二个按键(后IP搜索完成)正确发送3消息。
现在,您可以重复发送消息,它会工作,直到你等待(约一分钟,直到ADRESS翻译被再度迷失),那么你将再次看到辍学。

As you can see the first sending initiated a ARP search for the IP. While that search was pending the first 2 of the 3 successive sends were lost. The second keystroke (after the IP search was complete) properly sent 3 messages. You may now repeat sending messages and it will work until you wait (about a minute until the adress translation gets lost again) then you will see dropouts again.

这意味着:发送UDP消息,但存在未处理ARP请求时,没有发送缓冲区!所有消息迷路除了最后一个。
同时的sendto不会阻止,直到成功交付,并没有返回错误!

嗯,这让我惊讶,并让我有点难过,因为这意味着我不得不忍受我目前的解决办法或实施ACK系统,一次只能发送一个消息,然后等待回复 - 这将不很容易更多的,并暗示很多困难。

Well, that surprises me and makes me a little bit sad, because it means that I have to live with my current workaround or implement an ACK system that only sends one message at a time and then waits for reply - which would not be easy any more and imply many difficulties.

推荐答案

它已经被别人回答后,但它直接关系我长的张贴本。

I'm posting this long after it's been answered by others, but it's directly related.

的Winsock丢弃的UDP数据包是否有针对目标地址(或目的地的网关)没有ARP表项。

Winsock drops UDP packets if there's no ARP entry for the destination address (or the gateway for the destination).

因此​​它很可能一些第一UDP包被丢弃作为当时有没有ARP表项 - 而不像大多数其他操作系统,winsock的同时ARP请求仅完成1排队包。

Thus it's quite likely some of the first UDP packet gets dropped as at that time there's no ARP entry - and unlike most other operating systems, winsock only queues 1 packet while the the ARP request completes.

这是记载这里

ARP队列只有一个指定的目的地的出站IP数据报
  地址而IP地址解析成MAC地址。如果一个
  基于UDP的应用程序将多个IP数据报以一个单一的
  目的地址,它们之间没有停顿,一些
  如果不存在的ARP高速缓存条目已经报可以丢弃
  present。应用程序可以通过调用弥补这一点
  IPHLPAPI.DLL常规SendArp()建立ARP缓存项,前
  发送数据包的数据流。

ARP queues only one outbound IP datagram for a specified destination address while that IP address is being resolved to a MAC address. If a UDP-based application sends multiple IP datagrams to a single destination address without any pauses between them, some of the datagrams may be dropped if there is no ARP cache entry already present. An application can compensate for this by calling the Iphlpapi.dll routine SendArp() to establish an ARP cache entry, before sending the stream of packets.

同样的行为可以在<一个观察href=\"https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man4/arp.4.html\">Mac OS X 和 FreeBSD的

在接口请求一个地址的映射不
  在高速缓存中,ARP排队这就要求该消息
  映射和上广播的关联相关联的消息
  网络请求地址映射。如果响应是
  提供新的映射被缓存,任何进行中的消息是
  传输。在等待ARP将排队加一个包
  对于给映射请求的响应;仅最近
  ``'发送'包被保留。

When an interface requests a mapping for an address not in the cache, ARP queues the message which requires the mapping and broadcasts a message on the associated associated network requesting the address mapping. If a response is provided, the new mapping is cached and any pending message is transmitted. ARP will queue at most one packet while waiting for a response to a mapping request; only the most recently ``transmitted'' packet is kept.

这篇关于首先UDP消息发送给指定的远程IP丢失的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆