2014-09-06 4 views
1

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 Я не эксперт сокета программист Но, я написал несколько связанных сокет приложения, с некоторыми?.. предыдущая помощь с этого сайта. Но я знаю, что есть много чего не знаю. Спасибо за любую помощь!

+0

Я не совсем уверен, что отправка пакетов между двумя разными адресами на одном компьютере поддерживается. (Я знаю, что в некоторых конфигурациях виртуальная машина не может связываться с хостом, что, похоже, может быть связано.) С другой стороны, это может быть ошибка; он работает, если вы меняете один из номеров портов? Возможно, Windows ошибочно думает, что вы пытаетесь отправить пакет себе. –

+0

Да, вы можете отправлять данные с одного локального IP на другой локальный IP-адрес на том же компьютере. WinSock обрабатывает необходимый подключаемый модуль внутри, так что он физически не передает данные по сети. В среде VM вы должны использовать встроенный маршрутизатор VM для получения данных, передаваемых между VM и Host. Помните, что виртуальная машина действует как отдельная машина, поэтому ОС действует соответственно, поэтому виртуальные машины нуждаются в настройках виртуальной сети. –

+0

@RemyLebeau: Я пытался запомнить детали; Я думаю, что связь VM-host не работала, если виртуальная машина была настроена для совместного использования IP-адреса хоста через NAT. Виртуальная машина могла хорошо общаться с остальной локальной сетью, а не с хостом. Но теперь, когда я думаю об этом, программное обеспечение VM могло взаимодействовать с сетевым стеком ниже уровня WinSock, и в любом случае это было проблемой при общении с одним и тем же IP-адресом, а не с другим. Ваша интерпретация проблемы OPs представляется гораздо более вероятной. –

ответ

2

1004 9 (WSAEADDRNOTAVAIL) означает, что указанный IP-адрес недействителен. Таким образом, вы явно делаете что-то не так с переменной to, которую вы переходите на sendto(), и ваши сообщения об отладке, вероятно, скрывают проблему.

Например, использование ipv6rev() является для меня подозрительным. Если вы правильно отслеживаете IP-адреса, вам не нужно их отменять, так как они должны быть в правильном формате с самого начала. Для отображения вы должны использовать функцию, например InetNtop(), или RtlIpv6AddressToString() вместо их форматирования вручную.

Это означает, что переменная to, скорее всего, не в том формате. Похоже, что to заполняется с использованием данных от rtu_to_ipv6_map[], но вы не указали, как вы заполняете этот массив, поэтому трудно точно знать, является ли это причиной вашей корневой проблемы.

Это такая ситуация, когда вам действительно нужно предоставить SSCCE, чтобы другие могли воспроизвести проблему.

+0

Эй, Реми, ты повсюду, не так ли? ЛОЛ. Я делаю много Delphi, или, по крайней мере, привык, поэтому вы много раз помогали мне. Я начну использовать ваше предложение для форматирования адреса и работы оттуда. – user3681853

+0

Remy, я изменил код, чтобы использовать InetNtop(), и получил те же результаты, что и для распечатки. Я обновил свой вопрос с пересмотром. Затем я буду работать над SSCCE. Благодарю. – user3681853

+0

Я сделал небольшую тестовую программу, и она работает. Так что, должно быть, что-то не так с моей основной программой.Я заметил, что я поменял параметры в вызове memset(), где меняют размер и значение байта. Возможно, в этом и проблема, я буду тестировать дальше. Спасибо за помощь. – user3681853

 Смежные вопросы

  • Нет связанных вопросов^_^