Winapi 在UDP连接中的sendto()上获取错误10049(地址不可用),但bind()已工作

Winapi 在UDP连接中的sendto()上获取错误10049(地址不可用),但bind()已工作,winapi,udp,winsock2,sendto,Winapi,Udp,Winsock2,Sendto,编辑#2:问题是我愚蠢地将memset参数的顺序向后,因此,我没有将我的结构归零,因此在一些很少使用的字段中肯定有一些垃圾值。这大概解释了为什么它最初在我的系统上工作,而不是在客户上。我想我甚至没有收到编译器的警告 编辑#1:Remy建议我使用inentop而不是我自己的小ipv6rev()函数来打印IPv6地址。我做到了,得到了基本相同的结果。他的下一个建议是建立一个SSCCE,我将对此进行研究。但是,就目前而言,我只是编辑它来说明if inentop()的用法 我正在编写的应用程序是一种软件

编辑#2:问题是我愚蠢地将memset参数的顺序向后,因此,我没有将我的结构归零,因此在一些很少使用的字段中肯定有一些垃圾值。这大概解释了为什么它最初在我的系统上工作,而不是在客户上。我想我甚至没有收到编译器的警告

编辑#1:Remy建议我使用inentop而不是我自己的小ipv6rev()函数来打印IPv6地址。我做到了,得到了基本相同的结果。他的下一个建议是建立一个SSCCE,我将对此进行研究。但是,就目前而言,我只是编辑它来说明if inentop()的用法

我正在编写的应用程序是一种软件路由器,我在一个套接字(碰巧是IPv4)上获取数据,然后在IPv6 UDP上发送另一个套接字。我让它在我的机器上工作,但是,当我在customer上安装我的应用程序时,sendto调用失败。我最初是与另一台机器通信,但是为了使测试尽可能简单,我将UPD IPv6接收器放在同一台机器上,具有自己的IP。使用netstat,我似乎看到我已正确绑定:

  UDP    [2620:175:e10:2000:10:90:177:104]:20000  *:*
 [NATerator.exe]
  UDP    [2620:175:e10:2000:10:90:177:fff0]:20000  *:*
 [node.exe]
“NATerator”是我的软件路由器应用程序,接收器是Java应用程序(node.exe),因此,它们都绑定到端口20000,但IP地址不同。所以,我想我应该可以从…:104发送到…:fff0

但是sendto()在10049时失败。这似乎表明我正在为套接字发送错误的IP地址或端口。所以,我添加了调试消息来打印IP地址和端口,看起来我发送到了正确的地址。调试消息将打印出来:

2014-09-08 05:17:47.155 NATERATOR 7564 [TID=0x4cdc] - omniSocketThread: socket 2264 received bytes 24. NAT ok, calling sendto() 2620:0175:0e10:2000:0010:0090:0177:fff0 port 20000 {.\NATerator.cpp:669}
2014-09-08 05:17:47.181 NATERATOR 7564 [TID=0x4cdc] - omniSocketThread: Error sending data 10049
以下是sendto之前调试消息的代码,然后是对sendto的调用和之后的调试:

char ipv6String[100];
sockaddr_in6 *ipv6_addr;
ipv6_addr = (sockaddr_in6 *) &to;
InetNtop(AF_INET6, &ipv6_addr->sin6_addr, ipv6String, sizeof(ipv6String));

cpu_debug(CPU_DEBUG_ERROR,
    "omniSocketThread: socket %d received bytes %d. NAT ok, calling sendto() IP %s port %d\n",
    *csock, bytecount, ipv6String, htons(ipv6_addr->sin6_port));

bytecount = sendto(rtusock, (char *) buffer, bytecount, 0, (const sockaddr *) &to, tolen);

if(bytecount==SOCKET_ERROR)
{
        "omniSocketThread: Error sending data %d\n", WSAGetLastError());
    continue;
}
请注意,“cpu_debug”是一个内部调试记录器,其运行方式与printf()类似

我最初打开套接字的代码在这里。我目前没有设置任何套接字选项。我不确定我需要什么。我只调用socket()和bind(),如下所示:

lookupHost函数在in6_addr结构中得到填充,我认为它必须工作,因为nestat显示了应用程序绑定。“RTU端口”定义为20000。我应该在所有大写字母中使用这个名称,因为它是一个#define常量。因此,socket()和bind()调用的创建看起来就像工作一样。但也许我需要一些插座选项集

无论如何,最后一段相关代码是我填写“to”结构的地方。其定义如下:

struct      sockaddr_storage to;
int         tolen;

tolen = sizeof(to);
我有一个函数,用于填充:

bool omniNATerator(struct sockaddr_storage *to, USHORT received_dest)
{
    struct sockaddr_in6 *ipv6_addr = (sockaddr_in6 *) to;

    memset(to, sizeof(sockaddr_storage), 0);
    memcpy(&ipv6_addr->sin6_addr, &rtu_to_ipv6_map[received_dest], sizeof(in6_addr) );
    ipv6_addr->sin6_family = AF_INET6;
    ipv6_addr->sin6_port = htons(rtuport);
其中rtu_到_ipv6_映射定义如下:

in6_addr rtu_to_ipv6_map[65536];
而且,我有理由相信该数组中的值是正确的地址,因为我在调试消息中将其解包回来,并且它正确地声明了目标地址

所以,也许我忽略了一些简单的事情。但是,就我所见,我已经打开了套接字,我正在发送到一个可用且合理的IP地址。(我可以ping这两个IP地址。所以它应该可以工作,但它没有。你知道我可能会错过什么吗?如果我很愚蠢,也许不会对我投太坏的一票,哈哈

哦,我不妨列出IPconfig的输出:

Ethernet adapter IPv6:

   Connection-specific DNS Suffix  . :
   IPv6 Address. . . . . . . . . . . : 2620:175:e10:2000:10:90:177:104
   IPv6 Address. . . . . . . . . . . : 2620:175:e10:2000:10:90:177:fff0
   Link-local IPv6 Address . . . . . : fe80::cdd7:56a8:1afd:39e9%13
   Default Gateway . . . . . . . . . :
有什么想法吗

顺便说一句,我不是一个专业的socket程序员。但是,我已经编写了一些与socket相关的应用程序,之前有一些来自这个网站的帮助。但是,我知道有很多我不知道。谢谢你的帮助!

10049(
WSAEADDRNOTAVAIL
)表示指定的IP地址无效。因此,您传递给
sendto()
to
变量显然有问题,调试消息可能隐藏了问题

例如,
ipv6rev()
的使用对我来说是可疑的。如果你正确地跟踪了IP,你不必反转它们,因为它们从一开始就应该是正确的格式。出于显示目的,你应该使用类似或的函数,而不是手动格式化它们

这表明
to
变量很可能是以错误的格式开始的。看起来
to
是使用
rtu_to_ipv6_map[]
中的数据填充的,但您没有显示如何填充该数组,因此很难确定这是否是您的根本问题所在


在这种情况下,您确实需要提供一个虚拟机,以便其他人可以重现问题。

我不完全确定是否支持在同一台计算机上的两个不同地址之间发送数据包。(我确实知道,在某些配置中,虚拟机无法与主机通信,这似乎是相关的。)另一方面,这可能是一个错误;如果您更改了其中一个端口号,它会工作吗?可能Windows错误地认为您正在尝试向自己发送数据包。是的,您可以在同一台计算机上从一个本地IP向另一个本地IP发送数据。WinSock在内部处理必要的连接,因此它不会在r网络。在虚拟机环境中,您必须使用虚拟机的内置路由器来获取虚拟机和主机之间传递的数据。请记住,虚拟机作为一台单独的机器,因此操作系统会相应地进行操作,这就是为什么虚拟机需要虚拟网络设置的原因。@RemyLebeau:我一直试图记住细节;我认为如果VM被设置为通过NAT共享主机的IP地址。VM可以很好地与本地网络的其余部分通信,只是不能与主机通信。但现在我想起来了,VM软件可能与WinSock级别以下的网络堆栈进行了接口,在任何情况下,与相同IP地址的通信都存在问题,不是吗你对OPs问题的解释似乎更有可能。@HarryJohnston:当我需要在主机和虚拟机之间交换数据时,我通常在我的虚拟机中设置纯主机网络。嘿,Remy,你
Ethernet adapter IPv6:

   Connection-specific DNS Suffix  . :
   IPv6 Address. . . . . . . . . . . : 2620:175:e10:2000:10:90:177:104
   IPv6 Address. . . . . . . . . . . : 2620:175:e10:2000:10:90:177:fff0
   Link-local IPv6 Address . . . . . : fe80::cdd7:56a8:1afd:39e9%13
   Default Gateway . . . . . . . . . :