我上有控制一批“运动员”“服务器”基于LAN解决方案时我选择的协议是UDP,因为它很容易,我不需要连接,我的流量仅包括简短的命令不时我想用广播消息的混合为球员个人的命令同步和单一目标的消息。
组播TCP将是一个选择,但它比较复杂,并不完全适合的任务,往往不能很好的硬件支持。
不幸的是我遇到了一个奇怪的问题:
这是使用“的sendto”发送到特定IP的第一个数据报丢失。 发送短的时间后,以相同的IP数据报的任何接收。 但是,如果我等待一段时间(几分钟)第一“的sendto”再次丢失。
广播数据包总是工作。 本地发送(在同一台计算机)总是工作。
我相信操作系统或路由器/交换机具有从IP到MAC地址的一些转换表时,不被用于一些分,不幸的是会导致丢失数据包,其被遗忘。 我所观察到不同的交换机/路由器硬件的行为,所以我怀疑是网络层中的窗口。
我知道,UDP是定义“不可靠”,但我不能相信这个去到目前为止,即使物理连接是否正常工作,一切都被很好地定义数据包可能会丢失。 然后,它会从字面上不值钱。
从技术上讲,我打开一个UDP套接字,将其绑定到一个端口和INADRR_ANY。 然后,我使用“的sendto”和“recvfrom的”。 我永远不会做一个连接 - 我不想因为我有几个球员。 据我所知UDP应该没有连接。
我目前的解决办法是,我经常发送无效数据报给所有特定玩家的IPS - 解决该问题,但其有点“不满意”
问:是否有人知道这个问题? 它从何而来? 我该如何解决呢?
编辑:
我煮下来到下面的测试程序:
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流量,按一个键,稍等片刻,再按下一个键。 你并不需要一个接收器上的远程IP,没有什么区别,除了你不会得到黑色标记为“不可达”的数据包。 这是你会得到什么:
正如你所看到的第一个发送发起的ARP搜索的IP。 而该搜索被挂起的3连续的第一2发送丢失了。 第二个按键(后IP搜索是完全的)正确发送3个消息。 现在,您可以重复发送消息,它会工作,直到你等待(约一分钟,直到ADRESS翻译被再度迷失),那么你将再次看到辍学。
这意味着:没有发送UDP消息时发送缓冲区,但存在未处理的ARP请求! 所有消息迷路除了最后一个。 还“的sendto”不会阻止,直到成功交付,并没有错误回报!
嗯,这让我惊讶,让我有点难过,因为这意味着我不得不住在一起,我目前的解决方法或实现一个ACK系统一次只能发送一个消息,然后等待回复 - 这是不容易的任何越来越意味着许多困难。