2010-02-26 34 views
20

Przez lata opracowałem małą masę aplikacji serwera/klienta C++ dla Windows przy użyciu WinSock (routery, serwery WWW/poczta/FTP, itd ... itd.).Konwersja aplikacji C++ TCP/IP z IPv4 na IPv6. Trudny? Warty zachodu?

Zaczynam myśleć coraz więcej o tworzeniu wersji tych aplikacji w IPv6 (oczywiście przy zachowaniu oryginalnej wersji IPv4).

Pytania:

  1. Co pułapek mogę napotkasz?
  2. Czy portowanie/konwersja są trudne?
  3. Czy konwersja jest tego warta?


Dla odniesienia (lub dla zabawy), można sneek na szczyt IPv4 code u podstaw moich wniosków.

Odpowiedz

18

getaddrinfo i getnameinfo są Twoimi przyjaciółmi. W miarę możliwości sugeruję, aby byli twoimi najlepszymi przyjaciółmi w dążeniu do zapewnienia obsługi IPv4 i IPv6 w istniejącej aplikacji.

Jeśli zrobisz to dobrze, dodając obsługę IPv6, skończysz także abstrakcję systemu do punktu, w którym nieznany przyszły protokół IP może działać bez modyfikacji kodu.

Zwykle podczas łączenia byś wypełnić strukturę gniazdo, port rodziny adresów, adres IP, adres/konwersji porty do sieci kolejność bajtów itp

Z getaddrinfo wyślesz adres IP lub nazwę hosta i port lub nazwa portu, i zwraca połączoną listę ze strukturami i wszystkim gotowym do przekazania bezpośrednio do socket() i connect().

getaddrinfo ma kluczowe znaczenie dla pracy z obu protokołów IP, ponieważ nie wie, czy gospodarz ma łączność IPv6 i IPv4 i wie, jeśli peer ma także patrząc na DNS AAAA vs A ewidencji i dynamicznie dane, który protokół (s) są dostępne do obsługi konkretnego żądania połączenia.

Odradzam korzystanie z inet_pton(), inet_addr() lub urządzeń, które są specyficzne dla wersji IP. Na platformie Windows konkretnie inet_pton() nie jest kompatybilny z wcześniejszymi wersjami MS Windows (XP, 2003 i inni), chyba że użyjesz własnego. Odradzaj także oddzielne wersje dla IPv4 i IPv6 ... Nie jest to możliwe, ponieważ jest to rozwiązanie techniczne, ponieważ w niedalekiej przyszłości oba protokoły będą musiały być używane równocześnie, a ludzie mogą nie wiedzieć z wyprzedzeniem, z których korzystać. Interfejsy gniazd są abstrakcyjne i łatwo jest wykryć obsługę podwójnego stanowiska lub IPv6, próbując utworzyć gniazdo IPv6 lub spróbować ustawić opcję gniazda dualstack IPv6 dla odbiorców. Nie ma powodu, aby powstała aplikacja nie działała w systemie, który nie obsługuje lub nie zna protokołu IPv6.

Dla połączeń wychodzących użyj PF_UNSPEC w getaddrinfo, aby rodzina adresów została wybrana podczas nawiązywania połączeń wychodzących. To, IMHO, jest lepsze niż podejście dualstack, ponieważ pozwala platformom, które nie obsługują dualstack do pracy.

W przypadku połączeń przychodzących można połączyć osobno gniazda IPv4/IPv6, jeśli jest to uzasadnione ze względu na projekt lub użycie dualstack, jeśli nie można wykonać osobnych programów nasłuchujących. Podczas korzystania z dualstack getnameinfo zwraca adres IPv6 dla adresów IPv4, które IMHO kończy się całkowicie bezużyteczne. Mały program narzędziowy może przekonwertować ciąg na normalny adres IPv4.

Z mojego doświadczenia wynika, że ​​po usunięciu zależności od określonych wersji IP zakończyło się to mniejszym kodem zarządzania gniazdem, niż to się zaczęło.

+1

Warto również zauważyć, że wszystkie te połączenia są na ogół przenośne między Windows, Mac OS X i Linux, z niewielkimi różnicami tu i tam. –

2

Przejrzyj dzienniki zmian niektórych projektów open source, które zaimplementowały protokół IPv6. Większość to kod Unix, ale Winsock jest bardzo podobny do gniazd BSD.

Exim, Courier, Squid, Apache, BIND DNS to tylko niektóre miejsca, od których można zacząć szukać.

12

Dodałem obsługę IPv6 do mojego wcześniejszego tylko IPv4 networking library około roku temu i nie było dla mnie strasznie trudne ani traumatyczne.

Jedyna różnica polega jak przechowywać adresy IP:

W IPv4 zapisać je jako sockaddr_in „s (lub jeśli jesteś niegrzeczny, jak ja, jak uint32_t'S).

Dla IPv6 trzeba przechowywać je jako „s (lub jakiejś podobnej konstrukcji 128-bit).

Dobrym krokiem sprzed konwersji byłoby przejść przez kod i znaleźć wszystkie miejsca, gdzie IPv4 adresy są obecnie przechowywane i abstrakcyjny je do ogólnej klasy adresów IP, które mogą być później przeprogramowana wewnętrznie się Adres IPv4: lub Adres IPv6.
ponownie test, aby upewnić się, że nic nie jest złamane w IPv4 trybie ... raz, że jest wyrejestrowany, powinieneś być w stanie dokonać przełącznik IPv6 z zaledwie kilku więcej zmian (głównie zmieniających PF_INET do PF_INET6, inet_aton() do inet_pton() itd.).

moja biblioteka nadal statki jak IPv4 tylko domyślnie, ale z możliwością definiowania makr preprocesora (-DMUSCLE_USE_IPV6) przekompilować go w IPv6-Aware trybie.
W ten sposób nadal można kompilować na systemach, które nie obsługują protokołu IPv6.Jedną z bardzo przydatnych funkcji, które znalazłem po drodze, jest Adres IPv6 odwzorowywany przez IPv4: Podając jeden z nich (w zasadzie adres IPv4 z przedrostkiem 0xFFFF), otrzymujesz gniazdo, które może komunikować zarówno IPv4, jak i IPv6, a tym samym serwer, który może komunikować się zarówno z klientami IPv4, jak i IPv6 jednocześnie, bez konieczności pisania osobnych ścieżek kodu IPv4 i IPv6 dla wszystkiego.

Co do tego, czy warto, to naprawdę zależy od tego, co zamierzasz zrobić z kodem. Powiedziałbym, że jest to dobre doświadczenie edukacyjne, jeśli nic innego, i pozwala na korzystanie z twojego oprogramowania w środowiskach IPv6, które z czasem stają się bardziej powszechne.

+0

Dzięki! Zdecydowanie brzmi, jakbyś tam był wcześniej !!! – NTDLS

+1

Zaktualizowałem link, jeśli ktoś jest zainteresowany, ponieważ wygasł. –

Powiązane problemy