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!