Verbindung IPv4-Clients auf IPv6-server: connection refused
Bin ich experimentiert mit IPv6-sockets, insbesondere die "dual-stack" - Funktion angeboten, die auf Windows Vista und höher, und offenbar auf Unix standardmäßig. Ich finde, dass wenn ich Binde meinen server an eine bestimmte IP-Adresse oder den Hostnamen Auflösung von meinem lokalen Rechner, ich kann nicht akzeptieren eine Verbindung von einem IPv4-client. Wenn ich binden INADDR_ANY, kann ich allerdings.
Bitte betrachten Sie den folgenden code für meinen server. Sie können sehen, dass ich von Microsoft halten Beratung mit der Erstellung eines IPv6-socket, dann die Einstellung IPV6_V6ONLY flag auf null:
addrinfo* result, *pCurrent, hints;
memset(&hints, 0, sizeof hints); //Must do this!
hints.ai_family = AF_INET6;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE; //We intend to use the addrinfo in a call to connect(). (I know it is ignored if we specify a server to connect to...)
int nRet = getaddrinfo("powerhouse", "82", &hints, &result);
SOCKET sock = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
int no = 0;
if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&no, sizeof(no)) != 0)
return -1;
if (bind(sock, result->ai_addr, result->ai_addrlen) == SOCKET_ERROR)
return -1;
if (listen(sock, SOMAXCONN) == SOCKET_ERROR)
return -1;
SOCKET sockClient = accept(sock, NULL, NULL);
Hier ist der code für meine Kunden. Sie können sehen, ich erstellen Sie einen IPv4-socket und versucht, eine Verbindung zu meinem server:
addrinfo* result, *pCurrent, hints;
memset(&hints, 0, sizeof hints); //Must do this!
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
if (getaddrinfo("powerhouse", "82", &hints, &result) != 0)
return -1;
SOCKET sock = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
int nRet = connect(sock, result->ai_addr, result->ai_addrlen);
Das Ergebnis von meinem Aufruf verbinden ist immer 10061: Verbindung verweigert.
Wenn ich meine server-code zu binden :: (oder übergeben Sie einen NULL-host zu getaddrinfo() (das gleiche)), und mein client-code, um eine NULL-host in die getaddrinfo () - Aufruf, dann die V4-client kann die Verbindung in Ordnung.
Kann mir jemand erklären, warum bitte? Ich habe nicht irgendetwas Lesen, was müssen wir angeben, eine NULL-host (daher verwenden INADDR_ANY) wenn wir wollen, dass dual-socket-Verhalten. Dies kann nicht vorgeschrieben werden, weil das, was ich haben einen mehrfach vernetzten host und möchte ich akzeptieren IPv4 auf nur einige der verfügbaren IP-Adressen?
BEARBEITEN 15/05/2013:
Dies ist die relevante Dokumentation, die Sie bekommen hat mich verwirrt, warum mein code nicht funktioniert:
Vom Dual-Stack für IPv6-Sockets Winsock-Anwendungen
"Windows Vista und höher bieten die Möglichkeit, eine einzelne IPv6
Buchse, die mit IPv6 und IPv4-Verkehr. Zum Beispiel, ein TCP
socket für IPv6 erstellt, in dual-stack-Modus, und
gebunden an port 5001. Dieser dual-stack-socket akzeptiert verbindungen aus
IPv6-TCP-clients, die eine Verbindung zu port 5001 und von IPv4-TCP-clients
die Verbindung zu port 5001.""Standardmäßig eine IPv6-socket erstellt, die auf Windows Vista und höher nur
betreibt über das IPv6-Protokoll. Um eine IPv6-socket-in
ein dual-stack-Buchse, die setsockopt-Funktion muss aufgerufen werden, mit der
IPV6_V6ONLY socket-option, um diesen Wert auf null gesetzt, bevor die Steckdose
ist gebunden an eine IP-Adresse. , Wenn die IPV6_V6ONLY socket-option gesetzt ist
zu null, wird ein socket erstellt, für die Adressfamilie AF_INET6 verwendet werden kann
zum senden und empfangen von Paketen zu und von eine IPv6-Adresse oder ein IPv4 -
zugeordnete Adresse. (Hervorhebung von mir)"
bind
ist explizit eine IPv6-Endpunkt, und nicht eine wildcard.Ich sehe nicht, was du meinst, sorry. Können Sie das klären?
Verbindlich implementiert einen filter, um nur die Daten annehmen mit der destination address matching der gebundenen Adresse. IPv4-Pakete haben eine Ziel-IPv4-Adresse wird daher abgelehnt.
Danke, ich habe das Prinzip jetzt verinnerlicht, aber durch den Aufruf von setsockopt mit IPPROTO_IPV6 ich - laut Dokumentation - aktivieren Sie diese Buchse, um auch eingehende IPv4-verbindungen. Siehe auch den Kommentar habe ich unten geschrieben auf Sander ' s Kommentar...
InformationsquelleAutor Wad | 2013-05-10
Du musst angemeldet sein, um einen Kommentar abzugeben.
IPv4 und IPv6 sind zwei separate Protokolle. Pakete eines Protokolls kann nicht verarbeitet werden mit dem anderen Protokoll. Deshalb ist das Konzept des Dual-Stack vorhanden ist: Ihr system läuft sowohl in der IPv4-und IPv6-Protokoll-stacks, der sowohl IPv4-und IPv6-Adressen, etc.
Betriebssysteme haben einen trick, wo können Sie eine IPv6-socket, horcht auf, alle IPv4-und IPv6-Adressen. Sie müssen noch zu haben, beide Adressfamilien auf dem host, und es funktioniert nur, wenn Sie binden an die wildcard-Adresse. Einmal binden Sie, die Buchse, um eine Feste Adresse, die nicht mehr funktioniert und es funktioniert nur die Adresse, die Sie gebunden haben.
Also, wenn Sie wollen, hören Sie auf, alle verfügbaren Adressen, die dann die Einstellung IPV6_V6ONLY auf 0 und hören auf die wildcard-Adresse zu arbeiten. Die IPv4-clients als auch mit IPv6-Adressen beginnend mit
::ffff:
mit den letzten 32 bits enthalten die IPv4-Adresse.Wenn Sie möchten, binden Sie an spezifische Adressen, die Sie benötigen sockets gebunden an jede der Adressen, die du hören möchtest. Dann brauchen Sie, um zu verwenden, D. H.
select(...)
zu überwachen diejenigen, sockets und zu reagieren, um diejenigen, die aktiv werden, weil jemand verbindet sich zu Ihnen.Die offizielle Dokumentation ist RFC 3493: tools.ietf.org/html/rfc3493.html. Aber dieses Szenario wird nicht beschrieben, da dies technisch unmöglich. Wenn binden Sie einen server, um eine IPv6-Adresse, dann kann der client nur eine Verbindung, wenn Sie mit, dass genaue Adresse als die Zieladresse. Eine IPv4-only-client kann keine Verbindung zu einem IPv6-Adresse, ebenso wie ein nur-IPv6-client kann keine Verbindung zu einer IPv4-Adresse. Quelle und Ziel muss immer der gleiche Protokoll. IPv6 ist nicht abwärtskompatibel mit IPv4 auf den Draht...
Danke Sander. Ich bin die Bindung an IPv6-Adressen, ja, aber wie oben erwähnt Steve-o durch die Einstellung teh IPPROTO_IPV6 die Dokumentation behauptet, dass meine IPv6-socket akzeptiert auch eine IPv4-client: die IPv4-Adresse zugeordnet werden, um eine IPv6. In der Tat, wenn ich laufen meine server und Blick auf TCPView, nach dem setsockopt () - Aufruf sehe ich beiden gebunden sockel Kraftpaket, eine von jeder IPv4-und IPv6-Protokoll. Das ist, warum ich kann nicht verstehen, warum dies noch immer nicht...
Das hat tatsächlich funktioniert, wenn Sie binden an die catch-all-Adresse. Binden Sie den server zu einem bestimmten realen IPv6-Adresse. Aber der AUFTRAGGEBER kann nicht wegen einer IPv4-only-client benötigt eine IPv4-Ziel-Adresse zu verbinden, und das gibt es nicht, weil Sie gebunden der server nur eine IPv6-Adresse. Wenn Sie möchten, dass ein server akzeptieren IPv4-verbindungen auf einem IPv6-socket-dann würden Sie zu binden, müssen die server an das IPv6-Gemappte IPv4-Adresse des server zusätzlich zu globalen IPv6-Adresse, die Sie binden. Sie müssen, um eine IPv4-Adresse für den client zu verbinden.
Dieser Teil: "zum senden und empfangen von Paketen zu und von eine IPv6-Adresse oder ein IPv4-mapped-address" ist verwirrend. Blick auf die software-Schicht, die Buchse kann im Umgang mit IPv6 und IPv6-Gemappte IPv4-Adressen. Es sagt nichts anderes und auf dem Draht IPv4 und IPv6 sind nicht kompatibel. So einem IPv4-host muss eine IPv4-Ziel-Adresse zu verbinden. IPv6-Gemappte IPv4-Adressen sind tatsächlich IPv4-Adressen dargestellt, die als IPv6-Adressen. Das binden einer IPv6-socket an eine solche Adresse tatsächlich bindet an eine IPv4-Adresse. Die Bindung an nur eine IPv6-Adresse wird es unmöglich machen, für IPv4-clients zu verbinden.
InformationsquelleAutor Sander Steffann
Diesen link http://www.masterraghu.com/subjects/np/introduction/unix_network_programming_v1.3/ch12lev1sec2.html gibt weitere Informationen über die IPv4-und IPv6-Verbindung,
InformationsquelleAutor Sathish