2014-09-06 40 views
1

編輯#2:問題是我愚蠢地讓memset參數順序倒退,所以,我沒有過零我的結構,因此必須在一些很少使用的字段中有一些垃圾值。這大概解釋了爲什麼它最初在我的系統上工作,而不是在客戶上。我不認爲我甚至得到了一個編譯器警告。在UDP連接上sendto()獲取錯誤10049(地址不是avai),但bind()工作

編輯#1:雷米建議我使用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地址。所以,大概我應該可以從......發送到......: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()相同。

我最初打開套接字的代碼就在這裏。我目前沒有設置任何套接字選項。不知道我需要什麼。我只是調用套接字()和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()調用的創建看起來就像是工作。但也許我需要一些套接字選項設置?

無論如何,最後一段相關代碼就是我填寫「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_to_ipv6_map定義如下:

in6_addr rtu_to_ipv6_map[65536]; 

而且,我有理由相信,該數組中的值是正確的地址,因爲我將它解壓縮回調試消息中,並且它正確地指出了目標地址。

所以,也許我忽略了一些簡單的東西。但是,就我所見,我打開了套接字,我正在發送一個可用且合理的IP地址。 (我可以ping通兩個IP地址,所以它應該可以工作,但它不會。任何想法,我可能會失蹤?如果它是愚蠢的,也許不會downvote我太糟糕,哈哈

哦,我不妨列出從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

我不完全確定是否支持在同一臺計算機上的兩個不同地址之間發送數據包。 (我知道在某些配置中虛擬機無法與主機進行通信,這看起來可能是相關的。)另一方面,它可能是一個bug;如果更改其中一個端口號,它會起作用嗎?也許Windows錯誤地認爲你正試圖向你發送一個數據包。 – 2014-09-06 21:32:40

+0

是的,您可以將數據從一個本地IP發送到同一臺機器上的另一個本地IP。 WinSock在內部處理必要的連接,因此它不通過網絡物理傳輸數據。在VM環境中,您必須使用VM的內置路由器才能在VM和主機之間傳遞數據。請記住,虛擬機作爲一臺獨立的機器運行,因此操作系統會相應地執行操作,這就是虛擬機需要虛擬網絡設置的原因。 – 2014-09-06 21:59:02

+0

@RemyLebeau:我一直在努力記住細節;我認爲如果VM設置爲通過NAT共享主機的IP地址,VM主機通信不起作用。虛擬機可以很好地與本地網絡的其餘部分通話,而不是主機。但是現在我想到了,虛擬機軟件可能已經與WinSock級別以下的網絡堆棧進行了接口連接,並且在任何情況下,與同一個IP地址進行通信都是一個問題,而不是一個不同的問題。您對OP問題的解釋似乎更有可能。 – 2014-09-07 20:32:09

回答

2

1004 9(WSAEADDRNOTAVAIL)表示指定的IP地址無效。很明顯,你在to變量中做錯了,你將傳遞給sendto(),並且你的調試消息很可能隱藏了這個問題。

例如,使用ipv6rev()對我來說是可疑的。如果你正確地跟蹤IP地址,你不應該反轉它們,因爲它們應該從一開始就採用正確的格式。出於顯示目的,您應該使用像InetNtop()RtlIpv6AddressToString()這樣的功能,而不是手動格式化它們。

這表明to變量可能以錯誤的格式開頭。它看起來像to使用來自rtu_to_ipv6_map[]的數據得到填充,但是您沒有顯示如何填充該數組,所以很難確定它是否出現問題的根源。

這種情況下,你真的需要提供SSCCE,以便其他人可以重現該問題。

+0

嘿,雷米,你到處都不是嗎?大聲笑。我做了很多Delphi,或者至少已經習慣了,所以,你們多次幫助我。我將開始使用你的建議格式化地址,並從那裏開始工作。 – user3681853 2014-09-08 11:46:06

+0

雷米,我改變了代碼使用InetNtop(),我得到了相同的結果,相同的打印輸出。我修改了我的問題。我將在下一個SSCCE工作。謝謝。 – user3681853 2014-09-08 12:29:34

+0

我做了一個小測試程序,它的工作原理。所以,我的主程序一定是錯的。我注意到我交換了memset()調用中的參數,其中交換了大小和字節值。也許這就是問題所在,我會進一步測試。謝謝您的幫助。 – user3681853 2014-09-08 19:14:41

相關問題