2010-02-26 4 views
20

Im Laufe der Jahre habe ich eine kleine Masse von C++ Server/Client-Anwendungen für Windows mit WinSock (Router, Web/Mail/FTP-Server, etc ... etc ...) entwickelt.Konvertieren von C++ TCP/IP-Anwendungen von IPv4 zu IPv6. Schwer? Der Mühe wert?

Ich denke immer mehr darüber nach, eine IPv6-Version dieser Anwendungen zu erstellen (natürlich unter Beibehaltung der ursprünglichen IPv4-Version).

Fragen:

  1. Welche Fallen könnte ich den Weg laufen?
  2. Ist die Portierung/Konvertierung schwierig?
  3. Lohnt sich die Umwandlung?


Für eine Referenz (oder zum Spaß), können Sie einen Peak der IPv4 code im Kern meiner Anwendungen sneek.

Antwort

18

getaddrinfo und getnameinfo sind Ihre Freunde .. So weit wie möglich schlage ich vor, dass sie Ihre besten Freunde in Ihrer Suche nach IPv4 und IPv6-Unterstützung in einer bestehenden Anwendung sind.

Wenn Sie direkt IPv6-Unterstützung hinzufügen, wird das System bis zu dem Punkt abstrahiert, an dem ein unbekanntes zukünftiges IP-Protokoll ohne Code-Änderung ausgeführt werden kann.

Normalerweise, wenn Sie eine Verbindung eine Sockelstruktur ausfüllen würde, Port, Adressfamilie, IP-Adresse, Adresse/ports Umwandlung Byte-Reihenfolge zu vernetzen, usw.

Mit getaddrinfo Sie eine IP-Adresse oder den Hostnamen und Port senden oder Port-Name, und es gibt eine verkettete Liste mit den Strukturen und alles bereit, direkt in socket() und connect() übergeben werden.

getaddrinfo ist entscheidend für die mit beiden IP-Protokollen arbeiten, wie es weiß, ob der Host IPv6 oder IPv4-Konnektivität hat und es weiß, ob der Peer als auch tut, indem DNS AAAA vs A Aufzeichnungen suchen und dynamisch herausfindet, welches Protokoll (e) sind verfügbar, um die spezifische Verbindungsanforderung zu bedienen.

Ich rate dringend davon ab, inet_pton(), inet_addr() oder ähnliche Geräte zu verwenden, die IP-spezifisch sind. Auf der Windows-Plattform inet_pton() ist nicht kompatibel mit früheren Versionen von MS Windows (XP, 2003 ua), es sei denn, Sie rollen Ihre eigenen. Beraten auch gegen separate Versionen für IPv4 und IPv6 ... Dies ist als technische Lösung nicht praktikabel, weil in naher Zukunft beide Protokolle gleichzeitig verwendet werden müssen und die Leute möglicherweise nicht im Voraus wissen, was zu verwenden ist. Die Socket-Schnittstellen sind abstrakt und es ist leicht, Dual-Stack- oder IPv6-Unterstützung zu erkennen, indem Sie versuchen, einen IPv6-Socket zu erstellen oder die IPv6-Dualstack-Socket-Option für Listener festzulegen. Es gibt keinen Grund, warum die resultierende Anwendung nicht auf einem System ausgeführt wird, das IPv6 nicht unterstützt oder kennt.

Für ausgehende Verbindungen verwenden Sie PF_UNSPEC in getaddrinfo, so dass die Adresse Familie für Sie ausgehende Verbindungen ausgewählt wird. Dies ist IMHO besser als der Dual-Stack-Ansatz, da es Plattformen ermöglicht, die Dual-Stack nicht unterstützen.

Bei eingehenden Verbindungen können Sie IPv4/IPv6-Sockets entweder separat binden, wenn dies aufgrund des Designs sinnvoll ist, oder Dualstack verwenden, wenn Sie keine separaten Listener verwenden können. Bei Verwendung von Dualstack gibt getnameinfo eine IPv6-Adresse für IPv4-Adressen zurück, die IMHO ziemlich nutzlos ist. Ein kleines Dienstprogramm kann die Zeichenfolge in eine normale IPv4-Adresse konvertieren.

Aus meiner Erfahrung, wenn Sie richtig gemacht haben Sie Abhängigkeiten von bestimmten IP-Versionen entfernt und endete mit weniger Socket-Management-Code als Sie gestartet.

+1

Es ist auch erwähnenswert, dass alle diese Anrufe in der Regel zwischen Windows, Mac OS X und Linux mit nur geringen Unterschieden hier und da portierbar sind. –

2

Sehen Sie sich die Änderungsprotokolle einiger Open Source-Projekte an, die IPv6 implementiert haben. Das meiste davon ist Unix-Code, aber Winsock ist BSD-Sockets sehr ähnlich.

Exim, Kurier, Tintenfisch, Apache, BIND DNS sind einige Orte zu suchen beginnen.

12

Ich habe IPv6-Unterstützung für mein vormals nur IPv4-ähnliches networking library vor etwa einem Jahr hinzugefügt, und ich fand es nicht schrecklich schwierig oder traumatisierend zu tun.

Der einzige große Unterschied ist, wie Sie speichern IP-Adressen:

In IPv4 Sie speichern sie als sockaddr_in ‚s (oder wenn Sie Frech, wie ich, als uint32_t des).

Für IPv6 müssen Sie sie als 's (oder eine gleichwertige 128-Bit-Struktur) speichern.

Ein guter Pre-Umwandlungsschritt wäre durch den Code zu gehen und all der Orte zu finden, wo IPv4 Adressen derzeit gespeichert sind, und abstrakt sie aus in eine generische IP-Adresse-Klasse, die später intern neu implementiert werden kann, um zu sein entweder eine IPv4-Adresse oder eine IPv6-Adresse.
Dann erneut zu testen, dass nichts gebrochen ist in IPv4 Modus zu machen ... einmal, dass ausgecheckt ist, sollten Sie in der Lage sein, den Schalter auf IPv6 mit nur noch ein paar Änderungen vornehmen (hauptsächlich PF_INET-PF_INET6 ändern, inet_aton() zu inet_pton(), etc ...).

Meine Bibliothek noch Schiffe als IPv4-only standardmäßig, aber mit der Option, einen Präprozessormakro definieren (-DMUSCLE_USE_IPV6) es neu kompiliert in IPv6-fähigen Modus.
So kann es immer noch auf Systemen kompiliert werden, die IPv6 nicht unterstützen.Eine sehr nützliche Funktion, die ich auf dem Weg gefunden habe, ist IPv4-gemappte IPv6-Adressen: Durch Angabe einer dieser (im Wesentlichen eine IPv4-Adresse mit 0xFFFF vorangestellt), erhalten Sie einen Socket, der sowohl IPv4 und IPv6 und damit sprechen kann ein Server, der sowohl mit IPv4- als auch mit IPv6-Clients gleichzeitig kommunizieren kann, ohne separate IPv4- und IPv6-Codepfade für alles schreiben zu müssen.

Ob es sich lohnt, hängt davon ab, was Sie mit dem Code machen wollen. Ich würde sagen, es ist eine gute pädagogische Erfahrung, wenn nichts anderes, und es ermöglicht Ihre Software in IPv6-Umgebungen verwendet werden, die im Laufe der Zeit häufiger werden.

+0

Vielen Dank !! Es klingt definitiv so, als wärst du schon mal dort gewesen !!! – NTDLS

+1

Ich habe den Link aktualisiert, wenn jemand interessiert ist, da es abgelaufen ist –

Verwandte Themen