Oprogramowanie komunikacyjne dla Internetu rzeczy Laboratorium nr 4 komunikacja unicastowa IPv6 Celem ćwiczenia jest zdobycie umiejętności programowania komunikacji unicastowej za pomocą protokołu IPv6 w językach C i C# na poziomie interfejsu gniazd. Materiały dotyczące poszczególnych funkcji były podane na wykładzie. 1. Narzędzia i konfiguracja Dla potrzeb laboratorium w SO Windows wykorzystany zostanie kompilator języka C++ DevCpp. Wersję instalacyjną oraz wersję przenośną można pobrać ze strony: http://sourceforge.net/projects/orwelldevcpp/files/. W konfiguracji linkera koniecznie należy dołączyć bibliotekę ws2_32.dll. W tym celu w menu należy wybrać kolejno: Tools/Options/Compiler Options z dopisać l ws2_32 jak na poniższym rysunku. W systemach wbudowanych użyte zostanie środowisko.net (dla SO Linux wersja otwarto źródłowa Mono) i język programowania C# http://www.mono-project.com. W SO Linux do kompilacji kodu C# można wykorzystać kompilator Mono mcs albo Microsoft csc np.: mcs kod.cs mono kod.cs Przy pracy z interfejsem graficznym (MS Windows, X Window) pomocne może być środowisko IDE MonoDevelop http://www.monodevelop.com. Ostatnia aktualizacja: 2017-05-17-1 -
2. Najważniejsze struktury danych i najważniejsze funkcje 2.1.Struktura addrinfo struct addrinfo { int ai_flags; int ai_family; int ai_socktype; int ai_protocol; socket_t ai_addrlen; char *ai_canonname; struct sockaddr *ai_addr; struct addrinfo *ai_next; }; Wartości poszczególnych pól struktury: ai_flags ai_family ai_socktype ai_protocol ai_addrlen ai_canonname ai_addr ai_next AI_PASSIVE 0x01 Adres może być użyty w funkcji bind AI_CANONAME 0x02 Adres jest adresem domenowym AI_NUMERICHOST 0x04 Adres jest adresem numerycznym IP AF_UNSPEC 0 Protokół nie jest wyspecyfikowany AF_INET 2 Protokół IPv4 AF_INET6 23 Protokół Ipv6 AI_STREAM 1 Protokół transportowy TCP dla AF_INET i AF_INET6 AI_DGRAM 2 Protokół transportowy UDP dla AF_INET i AF_INET6 AI_RAW 3 Tzw. surowe pakiety umożliwiają manipulację nagłówkiem protokołów kolejnej warstwy IPPROTO_TCP 6 Protokół TCP IPPROTO_UDP 17 Protokół UDP Rozmiar w bajtach struktury ai_addr Adres jako łańcuch znaków Adres sieciowy Wskaźnik na kolejną strukturę addrinfo 2.2.Struktury sockaddr W zależności od wartości parametru sa_family struktury sockaddr są różnie zdefinowane. Należy pamiętać, że adresy w strukturach sockaddr są umieszczane w sieciowej kolejności bajtów. struct sockaddr { unsigned short sa_family; // address family, AF_xxx char sa_data[14]; // 14 bytes of protocol address }; // IPv4 AF_INET sockets: struct sockaddr_in { short sin_family; // e.g. AF_INET, AF_INET6 unsigned short sin_port; // e.g. htons(3490) struct in_addr sin_addr; // see struct in_addr char sin_zero[8]; }; struct in_addr { unsigned long s_addr; // load with inet_pton() }; // IPv6 AF_INET6 sockets: struct sockaddr_in6 { short sin6_family; // address family, AF_INET6 u_short sin6_port; // port number, Network Byte Order Ostatnia aktualizacja: 2017-05-17-2 -
u_long sin6_flowinfo; // IPv6 flow information struct in6_addr sin6_addr; // IPv6 address u_long sin6_scope_id; // Scope ID }; struct in6_addr { unsigned char s6_addr[16]; // load with inet_pton() }; 2.3.Funkcja getaddrinfo() Funkcja getaddrinfo() zastępuje funkcję gethostbyname(), która obsługiwała wyłącznie protokół IPv4. int getaddrinfo(char*, char*, addrinfo*, addrinfo** ); Argumenty: 1. adres docelowy jako 2. port albo usługa połączenia 3. preferencje dla resolvera 4. wskaźnik na strukturę wyników Czwarty parametr zwraca wskaźnik na listę jednokierunkową struktur adresowych typu addrinfo. Będzie ona wykorzystywana we wszystkich kolejnych wywołaniach funkcji dotyczących obsługi interfejsu gniazd. Funkcja ta zwraca zero, gdy zakończy się sukcesem albo wartość mniejszą od zera sygnalizującą błąd. Strukturę wyników należy zwolnić po wykorzystaniu za pomocą funkcji freeaddrinfo(). int freeaddrinfo(addrinfo* ); 2.4 Obsługa IPv6 w języku C# Poprawną konwersję zapisów tekstowych adresów domenowych albo adresów IP na klasę IPAddress zapewnia metoda IPAddress[] System.Net.Dns.GetHostAddresses(string host). Zwaraca ona tablicę wszystkich adresów przypisanych do danej nazwy. Kolejność adresów wynika z preferencji zystemu (obecnie zawsze najpierw IPv6). Jeśli w systemie nie ma obsługi IPv6 albo połączenie jest nieaktywne zwracana lista nie zawiera adresów IPv6. Utworzenie gniazda dla IPv6 wymaga podania jako parametru System.Net.Sockets.AddressFamily.InterNetworkV6. Przykłady: UdpClient udpclient = new UdpClient(AddressFamily.InterNetworkV6); UdpClient udpserver = new UdpClient(port, AddressFamily.InterNetworkV6); TcpClient tcpclient = new TcpClient(AddressFamily.InterNetworkV6); TcpListener tcpserver = new TcpListener(IPAddress.IPv6Any, port); W SO Windows NT6 (Windows Vista i nowsze) wprowadzono funkcjonującą wcześniej w SO Linux funkcję umożliwiającą obsługę przychodzących połączeń zarówno IPv4 jak i IPv6 za pomocą pojedynczego gniazda IPv6 z wyzerowaną opcją IPV6ONLY. Dla środowiska.net 4.5 można taką obsługę włączyć dla gniazd TCP ustawiając właściwość DualMode na true, a dla obsługi UDP należy Ostatnia aktualizacja: 2017-05-17-3 -
wymienić gniazdo. Przychodzące połączenia IPv4 mają w tym rozwiązaniu adresy mapowane do IPv6 do postaci ::ffff:1.2.3.4. Przykład inicjacji serwera TCP do równoczesnej obsługi połączeń IPv4 i IPv6: tcp = new TcpListener(IPAddress.IPv6Any, port); tcp.server.dualmode = true; tcp.start(); Przykład inicjacji serwera UDP do równoczesnej obsługi połączeń IPv4 i IPv6: UdpClient udpserver = new UdpClient(port, AddressFamily.InterNetworkV6); Socket socket = new Socket(AddressFamily.InterNetworkV6, SocketType.Dgram, ProtocolType.Udp); socket.dualmode = true; udpserver.client.close(); udpserver.client = socket; udpserver.client.bind(new IPEndPoint(IPAddress.IPv6Any, port)); Ostatnia aktualizacja: 2017-05-17-4 -
3.1. Odczytanie wszystkich adresów lokalnych interfejsów (język C) Program umożliwia wypisanie wszystkich adresów lokalnych interfejsów. Program obsługuje zarówno protokół IPv6 jak i IPv4. Uruchamiając z wiersza poleceń można podać, jako parametr, adres domenowy, dla którego zostaną zwrócone wszystkie adresy IP. Ostatnia aktualizacja: 2017-05-17-5-
3.2. Odczytanie wszystkich adresów lokalnych interfejsów (język C#) Program umożliwia wypisanie wszystkich adresów lokalnych interfejsów. Program obsługuje zarówno protokół IPv6 jak i IPv4. Uruchamiając z wiersza poleceń można podać, jako parametr, adres domenowy, dla którego zostaną zwrócone wszystkie adresy IP. Ostatnia aktualizacja: 2017-05-17-6 -
4.1. Klient połączenia TCP (język C) Program umożliwia wysłanie tekstu protokołem TCP i odebrania odpowiedzi w ramach tego samego połączenia. Program obsługuje zarówno protokół IPv6 jak i IPv4. Uruchamiając z wiersza poleceń można podać, jako parametry, adres, numer portu i treść wiadomości. Ostatnia aktualizacja: 2017-05-17-7-
4.2. Klient połączenia TCP (język C#) Program umożliwia wysłanie tekstu protokołem TCP i odebrania odpowiedzi w ramach tego samego połączenia. Program obsługuje zarówno protokół IPv6 jak i IPv4. Uruchamiając z wiersza poleceń można podać, jako parametry, adres, numer portu i treść wiadomości. Ostatnia aktualizacja: 2017-05-17-8 -
5.1. Echo serwer połączeń TCP (język C) Program przyjmuje połączenia i odsyła z powrotem dane przesłane protokołem TCP w ramach tego samego połączenia. Program obsługuje zarówno protokół IPv6 jak i IPv4. Uruchamiając z wiersza poleceń można podać, jako parametry, numer portu i lokalny adres interfejsu. Ostatnia aktualizacja: 2017-05-17-9-
5.2. Echo serwer połączeń TCP (język C#) Program przyjmuje połączenia i odsyła z powrotem dane przesłane protokołem TCP w ramach tego samego połączenia. Program obsługuje zarówno protokół IPv6 jak i IPv4. Uruchamiając z wiersza poleceń można podać, jako parametr, numer portu. Ostatnia aktualizacja: 2017-05-17-10 -
6.1. Klient komunikacji UDP (język C) Program umożliwia wysłanie tekstu protokołem UDP i odebrania odpowiedzi w ramach tego samego połączenia. Program obsługuje zarówno protokół IPv6 jak i IPv4. Uruchamiając z wiersza poleceń można podać, jako parametry, adres, numer portu i treść wiadomości. Ostatnia aktualizacja: 2017-05-17-11 -
6.1. Klient komunikacji UDP (język C#) Program umożliwia wysłanie tekstu protokołem UDP i odebrania odpowiedzi w ramach tego samego połączenia. Program obsługuje zarówno protokół IPv6 jak i IPv4. Uruchamiając z wiersza poleceń można podać, jako parametry, adres, numer portu i treść wiadomości. Ostatnia aktualizacja: 2017-05-17-12 -
7.1. Echo serwer komunikacji UDP (język C) Program przyjmuje przychodzące datagramy UDP i odsyła z powrotem dane przesłane protokołem UDP w ramach tego samego połączenia. Program obsługuje zarówno protokół IPv6 jak i IPv4. Uruchamiając z wiersza poleceń można podać, jako parametry, numer portu i lokalny adres interfejsu. Ostatnia aktualizacja: 2017-05-17-13 -
7.2. Echo serwer komunikacji UDP (język C#) Program przyjmuje przychodzące datagramy UDP i odsyła z powrotem dane przesłane protokołem UDP w ramach tego samego połączenia. Program obsługuje zarówno protokół IPv6 jak i IPv4. Uruchamiając z wiersza poleceń można podać, jako parametr, numer portu. Ostatnia aktualizacja: 2017-05-17-14 -