Programowanie Aplikacji Sieciowych
Transkrypt
Programowanie Aplikacji Sieciowych
Politechnika Białostocka Wydział Elektryczny Katedra Telekomunikacji i Aparatury Elektronicznej Pracownia Specjalistyczna Programowanie Aplikacji Sieciowych Ćwiczenie 3 Protokół HTTP – chunky transfer opracował mgr inż. Grzegorz Kraszewski Białystok 2007 Cel ćwiczenia Nawiązanie połączenia HTTP z serwerem teleinfo.pb.edu.pl na porcie 80, wysłanie zapytania, pobranie strony /reggae/index.php wysyłanej przez serwer z użyciem protokołu chunky transfer, wyświetlenie go jako tekst w oknie konsoli. Materiały źródłowe Dokument RFC 2616 „Hypertext Transfer Protocol – HTTP/1.1”, dostępny między innymi pod adresem http://www.ietf.org/rfc/rfc2616.txt. Sposób wykonania zadania Znaczna część zadania opiera się na zagadnieniach opracowanych w poprzednim ćwiczeniu. Najważniejszą różnicą jest konieczność obsłużenia podprotokołu transmisyjnego HTTP/1.1 znanego jako chunky transfer. Protokół ten pozwala serwerowi na wysłanie do przeglądarki danych, których długość nie jest znana przed zakończeniem ich generowania.W protokole HTTP/1.0 w takim wypadku po prostu należało odbierać dane aż do zamknięcia połączenia przez serwer. Mechanizm chunky transfer pozwala aplikacjom klienckim na łatwiejszą obsługę ściągania i buforowania danych. Polega on na tym, że dane są transmitowane jako seria bloków (ang. chunks). Liczba tych bloków jest nieznana, natomiast rozmiar każdego bloku jest przesyłany tuż przed jego danymi. W ten sposób aplikacja może zarezerwować bufor na blok, a następnie go przetworzyć. Serwery stosują chunked transfer w dwóch przypadkach. Pierwszy to strony generowane dynamicznie, na przykład przez PHP czy inne języki skryptowe.Drugi to strumieniowe przesyłanie multimediów za pośrednictwem HTTP (np. protokół Shoutcast). W obu przypadkach nie jest możliwe wykorzystanie pola Content-Length nagłówka HTTP, ponieważ ilość przesyłanych danych nie jest w tym momencie znana (w przypadku np. radia internetowego jest to ilość teoretycznie nieskończona). Wykrycie transmisji chunked Serwer informuje klienta o zastosowaniu trybu chunked transfer odpowiednim polem nagłówka odpowiedzi HTTP. Jest to pole Transfer-Encoding. Transfer-Encoding: chunked[CRLF] Warto zauważyć, że obsługa chunked transfer jest wymagana przez standard HTTP/1.1, to nie jest opcja! Struktura danych w transmisji chunked Dane podzielone są na bloki o dowolnej długości. Strukturę najlepiej będzie wyjaśnić na poniższym przykładzie. Każde przejście do następnej linii to sekwencja [CRLF], dla czytelności sekwencje te nie zostały umieszczone w przykładzie. Na początku mamy standardowy nagłówek HTTP, oczywiście ponieważ ma miejsce transmisja chunked, jednym z pól nagłówka jest Transfer-Coding z wartością „chunked”. Po pustej linii oddzielającej nagłówek od danych, następuje seria bloków danych, ilość tych bloków nie jest nigdzie określona. Odbieranie kolejnych bloków prowadzi się w pętli, aż do napotkania bloku o długości 0. Każdy blok składa się z dwóch części. Pierwsza z nich to pojedyncza linia tekstu zawierająca długość danych bloku w bajtach. Długość ta jest przedstawiona jako łańcuch tekstowy zawierający liczbę szesnastkową. W liczbie dopuszczalne są zera i spacje wiodące, wielkość liter oznaczających cyfry szesnastkowe od „A” do „F”, jest nieistotna. Po długości może (ale nie musi) nastąpić średnik i seria tzw. rozszerzeń, a więc danych postaci „nazwa=wartość”. Z reguły takie rozszerzenia nie występują, a jeżeli nawet, to najczęściej są ignorowane. Do odczytania długości bloku najwygodniej podać odebraną linię jako argument funkcji strtoul() z bazą systemu numerycznego równą 16. Funkcja automatycznie pominie zera i spacje wiodące, poradzi sobie z małymi i dużymi cyframi szesnastkowymi i zakończy konwersję po napotkaniu czy to końca linii, czy to średnika. HTTP/1.1 200 OK Content-Type: text/html; charset=utf-8 Transfer-Encoding: chunked Content-Coding: identity Date: Tue, Mar 2007 10:36:10 GMT pusta linia 758 1880 bajtów danych zakończonych sekwencją końca linii 13f2; cos=xx cosjescze=yy 5106 bajtów zakończonych sekwencją końca linii 008e2 2274 bajty zakończone sekwencją końca linii 0; blabla=34 fff=e pusta linia Po linii z długością bloku następuje podana ilość bajtów danych zakończona sekwencją CRLF (sekwencja nie jest częścią danych). Ostatni blok danych ma zawsze długość 0 i składa się tylko z pierwszej części (nie ma, rzecz jasna, danych). Po ostatnim bloku może jeszcze wystąpić tak zwany trailer, który ma postać podobną do nagłówka HTTP, z tą różnicą, że nie zawiera pierwszej linii. Trailer wystąpi jednak tylko wtedy, gdy w zapytaniu zgodzimy się na jego otrzymanie (Pole „TE:” nagłówka zapytania). Na zakończenie całej odpowiedzi HTTP następuje linia pusta. Poniżej przedstawiono algorytm odbioru danych poprzez HTTP z chunked transfer. START pobierz linię tekstu błąd odczytaj długość bloku długość bloku > 0 tak pobierz blok danych nie błąd STOP przetwórz blok danych pobierz CRLF błąd BŁĄD!