EDIT # 2: Проблема заключалась в том, что я тупо имел параметр memset, обратный порядок, поэтому я не был нулевым моя структура и, следовательно, должны иметь некоторые значения мусора в некоторых редко используемых полях. Что, по-видимому, объясняет, почему он первоначально работал на моей системе, но не на клиенте. Я не думаю, что у меня даже есть предупреждение компилятора.Получение ошибки 10049 (адрес не avai) на sendto() в соединении UDP, но bind() работал
EDIT # 1: Remy предложил использовать InetNtop вместо собственной функции ipv6rev(), чтобы распечатать адрес IPv6. Я сделал это и получил в основном те же результаты. Следующее его предложение - создать SSCCE, над которым я буду работать. Но на данный момент я просто редактирую это, чтобы отметить использование InetNtop().
Приложение, которое я пишу, является своего рода программным маршрутизатором, в котором я получаю данные на одном сокете (который является IPv4) и отправляет его на IPv6 UDP. Я работал над своей машиной, но когда я установил свое приложение у клиента, вызовы 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» является собственным debug logger, который работает как printf().
Код, в котором я первоначально открыл сокет, находится здесь. В настоящее время я не устанавливаю параметры сокета. Не уверен, что мне это нужно. Я просто называю сокет() и Bind() следующим образом:
rtusock = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
if (rtusock == -1)
{
return(false);
}
in6_addr ipv6addr;
lookupHost(local_ipv6, &ipv6addr);
memset(&sinIPv6, 0, sizeof(sinIPv6));
sinIPv6.sin6_family = AF_INET6;
// sinIPv6.sin6_addr = in6addr_any;
memcpy(&sinIPv6.sin6_addr, &ipv6addr, sizeof(in6_addr));
sinIPv6.sin6_port = htons(rtuport);
sockstatus = bind(rtusock, (struct sockaddr *) &sinIPv6, sizeof(sockaddr_in6));
if(sockstatus == -1)
{
return(false);
}
Функция lookupHost получает заливку в структуре in6_addr, который я думаю, должен работать, так как nestat показано применение связанного. «Rtuport» определяется как 20000. Я должен был сделать имя во всех кепках, так как это константа #define. Таким образом, создание вызовов socket() и bind() выглядит как работа. Но, возможно, мне нужны некоторые настройки сокетов?
Во всяком случае, последняя часть соответствующего кода - это место, где я заполняю структуру «до». Она определяется как:
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_to_ipv6_map определяется следующим образом:
in6_addr rtu_to_ipv6_map[65536];
И я достаточно уверен, что значение в этом массиве является правильным адресом, потому что я распаковываю его обратно в сообщении отладки и правильно указывает адрес назначения.
Итак, возможно, я пропускаю что-то простое. Но, как я вижу, у меня открыт сокет, я отправляю доступный и разумный IP-адрес. (Я могу пинговать оба IP-адреса, поэтому он должен работать, но это не так. Любая идея, что мне может не хватать? И если это глупо со мной, возможно, не слишком сильно меня занижает, LOL.
О, Я мог бы также перечислить выход из 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 . . . . . . . . . :
Таким образом, любые идеи
PS Я не эксперт сокета программист Но, я написал несколько связанных сокет приложения, с некоторыми?.. предыдущая помощь с этого сайта. Но я знаю, что есть много чего не знаю. Спасибо за любую помощь!
Я не совсем уверен, что отправка пакетов между двумя разными адресами на одном компьютере поддерживается. (Я знаю, что в некоторых конфигурациях виртуальная машина не может связываться с хостом, что, похоже, может быть связано.) С другой стороны, это может быть ошибка; он работает, если вы меняете один из номеров портов? Возможно, Windows ошибочно думает, что вы пытаетесь отправить пакет себе. –
Да, вы можете отправлять данные с одного локального IP на другой локальный IP-адрес на том же компьютере. WinSock обрабатывает необходимый подключаемый модуль внутри, так что он физически не передает данные по сети. В среде VM вы должны использовать встроенный маршрутизатор VM для получения данных, передаваемых между VM и Host. Помните, что виртуальная машина действует как отдельная машина, поэтому ОС действует соответственно, поэтому виртуальные машины нуждаются в настройках виртуальной сети. –
@RemyLebeau: Я пытался запомнить детали; Я думаю, что связь VM-host не работала, если виртуальная машина была настроена для совместного использования IP-адреса хоста через NAT. Виртуальная машина могла хорошо общаться с остальной локальной сетью, а не с хостом. Но теперь, когда я думаю об этом, программное обеспечение VM могло взаимодействовать с сетевым стеком ниже уровня WinSock, и в любом случае это было проблемой при общении с одним и тем же IP-адресом, а не с другим. Ваша интерпретация проблемы OPs представляется гораздо более вероятной. –