Interfejs programowy WinInet, WinHttp Aplikacja httpget dr Zbigniew Lipiński Instytut Matematyki i Informatyki ul. Oleska 48 50-204 Opole zlipinski@math.uni.opole.pl
Protokół HTTP HTTP, ang. Hypertext Transfer Protocol, Wersja HTTP/1.0 opisana w specyfikacji RFC 1945. Wersja HTTP/1.1 opisana w specyfikacji RFC 2068. http://www.rfc-editor.org/ Protokół HTTP wykorzystywany jest do komunikacji między klientem z serwerem WWW. Domyślny port nasłuchiwania serwera WWW to port TCP 80. 2
Uniform Resource Identifier Uniform Resource Identifier (URI) jest stringiem, który poprzez nazwę, adres lub inną charakterystykę służy do identyfikacji zasobów w sieci internetowej. Uniform Resource Identifier (URI) znane są jako: adresy WWW, Universal Document Identifiers (UDI), Universal Resource Identifiers (URI), kombinacja Uniform Resource Locators (URL) i Uniform Resource Names (URN). Uniform Resource Locators (URL), RFC 1738, to string reprezentujący zasoby w Internecie. W specyfikacji RFC 1630 skrót URL wyjaśniony jest jako Universal Resource Identifiers dla WWW: URL jest stringiem URI, który wskazuje na obiekty i protokół dostępu w sieciach internetowych. 3
Struktura adresu URL Składnia adresu URL w notacji BNF: <scheme>:<scheme-specific-part> Możliwe artości scheme : ftp File Transfer protocol http Hypertext Transfer Protocol gopher The Gopher protocol mailto Electronic mail address news USENET news nntp USENET news using NNTP access telnet Reference to interactive sessions wais Wide Area Information Servers file Host-specific file names prospero Prospero Directory Service 4
Interfejs programowy WinInet WinInet API jest zbiorem obiektów, operacji, funkcji, które realizują funkcjonalność aplikacji sieciowych charakterystycznych dla warstw aplikacji, prezentacji, sesji modelu OSI. WinInet API pozwala tworzyć aplikacje sieciowe bez konieczności programowania funkcjonalności w niższych warstwach modelu OSI (protokołów rodziny TCP/IP, WinSock API). WinInet API pozwala na tworzenie aplikacji sieciowych (klientów usług) które mogą: pobierać strony HTML z serwera WWW za pomocą protokołu HTTP, komunikować się z serwerem FTP w celu transferu plików, wykorzystywać system Gopher w celu dostępu do zasobów Internetu. WinInet API pozawala tworzyć aplikacje sieciowe wykorzystujące protokoły: HTTP FTP Gopher. 5
Wybrane funkcje WinInet API Wybrane funkcje WinInet API: InternetOpen() Funkcja inicjalizuje użycie przez aplikacje funkcji Win32 Internet API, tworzy główny uchwyt (root HINTERNET handle). InternetCloseHandle() Funkcja zamyka uchwyt główny i wszystkie uchwyty potomne. InternetConnect() Funkcja otwiera sesję FTP, Gopher lub HTTP h z serwerem. Funkcja wymaga aby był utworzony uchwyt funkcją InternetOpen(). InternetQueryOption() - Funkcja służy do generowania zapytań o opcje połączeń. InternetSetOption(), InternetSetStatusCallback(), InternetConfirmZoneCrossing(), InternetTimeFromSystemTime() InternetReadFile() InternetOpenUrl() - Funkcja służy od pobierania plików z serwera. Funkcja wymaga utworzonego uchwytu funkcjami InternetOpenUrl(), FtpOpenFile(), GopherOpenFile() lub HttpOpenRequest(). dla adresów URL typu HTTP, FTP, Gopher lub uchwytów utworzonych funkcją HttpOpenRequest() używającej metody GET(). Funkcja służy do pobierania adresów URL FTP, Gopher lub HTTP. Funkcja wymaga utworzonego uchwytu funkcją InternetOpen(). 6
Wybrane funkcje WinInet API InternetWriteFile() - Funkcja zapisuje dane do otwartego pliku. Funkcja wymaga utworzonego uchwytu funkcją FtpOpenFile(). InternetCrackUrl() - Funkcja dzieli adres URL na składniki. InternetCreateUrl() - Funkcja tworzy adres URL (typ string) ze składników URL a. InternetCanonicalizeUrl() - Funkcja konwertuje adres URL na formę kanoniczną, patrz RFC 1945. The canonical form for "http" URLs is obtained by converting any UPALPHA characters in host to their LOALPHA equivalent (hostnames are case-insensitive), eliding the [ ":" port ] if the port is 80, and replacing an empty abs_path with "/". InternetCombineUrl() - Funkcja łączy adres główny z adresami alternatywnymi. HttpOpenRequest() Funkcja otwiera uchwyt HTTP request. HttpSendRequest() - Funkcja wysyła żądanie do serwera HTTP (serwera WWW). HttpQueryInfo() - InternetErrorDlg() - Funkcja służy do zapytań o informacje na temat HTTP request. Funkcja kieruje na wyjście dialogi o błędach. InternetGetCookie() - Funkcja zwraca cookies dla określonego adresu URL a i jego adresów głównych ( parent URLs ). 7
Wybrane funkcje Http WinInet API InternetSetCookie() - Funkcja ustawia cookie dla określonego adresu URL. CommitUrlCacheEntry() - Funkcja przechowuje dane w określonym pliku i kojarzy plik z adresem URL. CreateUrlCacheEntry(), GetUrlCacheEntryInfo(), ReadUrlCacheEntryStream(), SetUrlCacheEntryInfo(), UnlockUrlCacheEntryFile(), DeleteUrlCacheEntry(), FindCloseUrlCache(), FindFirstUrlCacheEntry(), FindNextUrlCacheEntry(). Wybrane funkcje FTP: FtpFindFirstFile(), FtpGetFile(), FtpPutFile(), FtpDeleteFile(), FtpRenameFile(), FtpOpenFile(), FtpCreateDirectory(), FtpRemoveDirectory(), FtpSetCurrentDirectory(), FtpGetCurrentDirectory(). Wybrane funkcje Gopher: GopherFindFirstFile(), GopherOpenFile(), GopherCreateLocator(), GopherGetAttribute(). 8
Uchwyty WinInet API Uchwyty internetowe internet handles służą do odbierania danych zwracanych przez funkcje WinInet API. Uchwyty WinInet API są typu HINTERNET. Hierarchia uchwytów WinInet API: uchwyt główny sesji, uchwyt zwracany przez funkcje InternetOpen(), uchwyty pochodne, uchwyty zwracane przez takie funkcje, jak np. InternetConnect(). 9
WinHTTP API Microsoft Windows HTTP Services API (WinHTTP API) jest uproszczoną wersją WinInet API (podzbiorem funkcji WinInet API bez funkcji FTP, Gopher). Implementacja API: Winhttp.h, Winhttp5.lib. Aplikacja wykorzystująca protokół HTTP pracująca jako serwer powinna być pisana z wykorzystaniem WinHTTP (nie WinInet). Elementy WinHTTP API: Obsługa protokołu HTTP/1.0, obsługa sesji złożonych z wielu zapytań (keep-alive, persistent connections) i mechanizm identyfikacji sesji za pomocą session cookies. Obsługa protokołu HTTP/1.1, obsługa kolejkowania anonimowych sesji. Obsługa protokołu Secure Sockets Layer (SSL 2.0, SSL 3.0, Transport Layer Security1.0), wykorzystanie certyfikatów do identyfikacji. Wbudowane funkcje identyfikacyjne serwera proxy, wykorzystanie mechanizmów identyfikacji i autoryzacji systemu Kerberos. Wbudowany interfejs do obsługi języków skryptowych. Obsługa Microsoft XML (MSXML). 10
Wybrane funkcje WinHTTP API: WinHTTP API WinHttpOpen(), WinHttpConnect(), WinHttpOpenRequest(), WinHttpSendRequest(), WinHttpReceiveResponse(), WinHttpQueryOption(), WinHttpCloseHandle() Uchwyty sesji HTTP: Generic Typ uchwytu Funkcja tworząca uchwyt WinHttpOpen(), WinHttpConnect(), WinHttpOpenRequest() Identyfikator hinternet Session WinHttpOpen() hsession Connection WinHttpConnect() hconnect Request WinHttpOpenRequest() hrequest Metody żądania stron: OPTIONS, GET, HEAD, PUT, POST, DELETE, TRACE, CONNECT. Szczegóły opisane są w specyfikacji RFC 2616 dla protokołu HTTP/1.1. 11
Metody żądania stron OPTIONS - metoda pozwala pobrać dane dotyczące opcji związanych z połączeniem HTTP, możliwości (capabilities) serwera WWW bez konieczności inicjowania procesu pobierania danych. GET - HEAD - POST - PUT - DELETE - TRACE - metoda pobierania istniejących zasobów z serwera WWW lub uruchomienie procesu generowania i zwracania danych przez serwer WWW do klienta. metoda służy do pobiera nagłówka dokumentu. Metodą HEAD nie można pobrać danych z obszaru BODY. metoda służy do pobiera danych z serwera WWW, wprowadzana bloków danych na serwer, w szczególności służy do przekazywania danych z formatek w celu przetwarzania ich na serwerze, uaktualniana bazy danych poprzez serwer WWW. metoda służy do wprowadzania danych na serwer WWW. URI w metodzie PUT służy do identyfikacji zasobu do którego mają być wprowadzone dane, nie wskazuje na proces przetwarzania danych na serwerze WWW lub tworzenia nowego zasobu. metoda służy do usuwania danych z serwera WWW. URI w metodzie DELETE oznacza zasób do usunięcia. metoda służy do zdalnego uruchamiania pętli zwrotnej na serwerze WWW, generowania odpowiedzi echa, tzn. klient wysyła wiadomość żądaniem jej zwrotu. Metoda służy klientowi do sprawdzania jakie dane mogą być zwracane przez serwer, do testów i diagnostyki serwera. Zwracane dane nie mogą być cache wane. CONNECT - metoda służy do komunikacji z serwerami proxy w celu przełączenia komunikacji w tryb tunelowy. 12
WinHTTP API. Kolejność wywoływania funkcji w sesji HTTP Kolejność wywoływania funkcji w sesji HTTP. Źródło: MSDN 13
Struktura Skladnikow URL a Definicja struktury SKLADNIKI_URL typedef struct { DWORD dwstructsize; // wielkość struktury liczona w bajtach LPSTR lpszscheme; // wskaźnik do zmiennej która przchowuje nazwę schematu DWORD dwschemelength; // wielkość nazwy schematu liczona w TCHAR INTERNET_SCHEME nscheme; // schemat URL a (typ protokołu), np.. http:, ftp: LPSTR lpszhostname; // wskaźnik do zmiennej która przchowuje nazwę hosta DWORD dwhostnamelength; // wielkość nazwy hosta liczona w TCHAR INTERNET_PORT nport; // numer portu (przekonwertowany) typ unsigned int LPSTR lpszusername; // wskaźnik do zmiennej która przchowuje nazwę użytkownika DWORD dwusernamelength; // wielkość nazwy użytkownika liczona w TCHAR LPSTR lpszpassword; // wskaźnik do zmiennej która przchowuje hasło DWORD dwpasswordlength; // wielkość hasła liczona w TCHAR LPSTR lpszurlpath; // wskaźnik do zmiennej która przchowuje ścieżkę URLa DWORD dwurlpathlength; // wielkość ścieżki URLa liczona w TCHAR LPTSTR lpszextrainfo; // wskaźnik do zmiennej która przchowuje dodatkowe informacje DWORD dwextrainfolength; // wielkość dodatkowych informacji liczona w TCHAR } SKLADNIKI_URL; 14
Typ wyliczeniowy INTERNET_SCHEME typedef enum { INTERNET_SCHEME_PARTIAL = -2, // Partial URL. INTERNET_SCHEME_UNKNOWN = -1, // Unknown URL scheme. INTERNET_SCHEME_DEFAULT = 0, // Default URL scheme. INTERNET_SCHEME_FTP, // FTP URL scheme (ftp:). INTERNET_SCHEME_GOPHER // Gopher URL scheme (gopher:). INTERNET_SCHEME_HTTP, // HTTP URL scheme (http:). INTERNET_SCHEME_HTTPS, // HTTPS URL scheme (https:). INTERNET_SCHEME_FILE, // File URL scheme (file:). INTERNET_SCHEME_NEWS, // News URL scheme (news:). INTERNET_SCHEME_MAILTO, // Mail URL scheme (mailto:). INTERNET_SCHEME_SOCKS, // Socks URL scheme (socks:). INTERNET_SCHEME_JAVASCRIPT, // JScript URL scheme (javascript:). INTERNET_SCHEME_VBSCRIPT, // VBScript URL scheme (vbscript:). INTERNET_SCHEME_FIRST = INTERNET_SCHEME_FTP, // Lowest known scheme value. INTERNET_SCHEME_LAST = INTERNET_SCHEME_VBSCRIPT // Highest known scheme value. } INTERNET_SCHEME, * LPINTERNET_SCHEME; 15
Specyfikacja funkcji InternetOpen() Nazwa funkcji : InternetOpen() Zwracana wartość: HINTERNET Argumenty: LPCTSTR lpszagent, DWORD dwaccesstype, LPCTSTR lpszproxyname (OPTIONAL), LPCSTR lpszproxybypass (OPTIONAL), DWORD dwflags lpszagent dwaccesstype lpszproxyname lpszproxybypass dwflags Nazwa programu (nazwa agenta http). Typ dostępu. Wartości: INTERNET_OPEN_TYPE_DIRECT, INTERNET_OPEN_TYPE_PROXY, INTERNET_OPEN_TYPE_PRECONFIG. Adres serwera proxy. Wartości: <adres> lub NULL. Alternatywny adres serwera proxy. Wartości: <adres> lub NULL. Opcje funkcji. Kombinacja wartości: INTERNET_FLAG_OFFLINE, INTERNET_FLAG_ASYNC. Opis : Funkcja inicjuje sesje, tworzy główny uchwyt internetowy (root HINTERNET handle). Wyjątki : Gdy otwarcie uchwytu się nie powiedzie funkcja zwraca NULL. INTERNET_OPEN_TYPE_PRECONFIG konfiguracja ma być pobrana z rejestrów 16
Specyfikacja funkcji InternetSetOption() Nazwa funkcji : InternetSetOption() Zwracana wartość: typ Bool, prawda lub fałsz. Argumenty: HINTERNET hinternet, DWORD dwoption, LPVOID lpbuffer, DWORD dwbufferlength. hinternet [in] uchwyt sesji. dwoption [in] opcje internetowe. lpbuffer [in] wskaźnik do bufora zawierającego ustawienia opcji internetowych. dwbufferlength [in] wielkość bufora. Opis : Funkcja ustawia opcje internetowe. Opcje internetowe (wybrane): INTERNET_OPTION_CONNECT_TIMEOUT INTERNET_OPTION_DATA_RECEIVE_TIMEOUT INTERNET_OPTION_CALLBACK INTERNET_OPTION_CODEPAGE INTERNET_OPTION_DATA_SEND_TIMEOUT 17
Specyfikacja funkcji InternetCrackUrl() Nazwa funkcji : InternetCrackUrl() Zwracana wartość: BOOL Argumenty : LPCSTR lpszurl, DWORD dwurllength, DWORD dwflags, LPURL_COMPONENTS lpurlcomponents lpszurl Adres do stringu zawierającego URL. dwurllength Długość adresu URL, NULL dla stringu ASCIIZ. dwflags Flagi. ICU_ESCAPE - Convert unsafe characters in the URL-path component to escape sequences. ICU_DECODE - Convert encoded characters back to their normal form. This can be used only if the user provides buffers to copy the components into. lpurlcomponents Składniki Url'a. Opis : Funkcja dzieli i przekazuje w częściach adres Url. 18
Specyfikacja funkcji InternetConnect() Nazwa funkcji : InternetConnect() Zwracana wartość: HINTERNET Argumenty :HINTERNET hinternetsession, LPCTSTR lpszservername, INTERNET_PORT nserverport, LPCTSTR lpszusername OPTIONAL, LPCTSTR lpszpassword OPTIONAL, DWORD dwservice, DWORD dwflags, DWORD dwcontext. hinternetsession - lpszservername - nserverport - lpszusername - lpszpassword - dwservice - dwflags - dwcontext - Uchwyt otwarty przez InternetOpen(). Adres serwera (może być adres IP zapisany w formie 10-tkowej). Numer portu TCP serwera. Wartości: INTERNET_INVALID_PORT_NUMBER, INTERNET_DEFAULT_FTP_PORT, INTERNET_DEFAULT_GOPHER_PORT, INTERNET_DEFAULT_HTTP_PORT, INTERNET_DEFAULT_HTTPS_PORT Adres stringu zawierającego nazwę użytkownika który się loguje. Adres stringu zawierającego hasło użytkownika. Typ usługi. Wartości: INTERNET_SERVICE_FTP, INTERNET_SERVICE_GOPHER, INTERNET_SERVICE_HTTP. Flagi usługi. Np. dla INTERNET_SERVICE_FTP flaga ma wartości: INTERNET_CONNECT_FLAG_PASS, IVE. Wartość definiowana przez aplikację aby zidentyfikować uchwyt dla wiadomości zwrotnej. An application-defined value that is used to identify the application context for the returned handle in callbacks. Opis : Funkcja otwiera sesje FTP, Ghoper, HTTP z serwerem. Funkcja wymaga uchwytu utworzonego przez InternetOpen(). 19
Nazwa funkcji : HttpOpenRequest() Zwracana wartosc: HINTERNET Specyfikacja funkcji HttpOpenRequest() Argumenty : HINTERNET hhttpsession, LPCTSTR lpszverb, LPCTSTR lpszobjectname, LPCTSTR lpszversion, LPCTSTR lpszreferer OPTIONAL, LPCTSTR FAR * lpszaccepttypes OPTIONAL, IN DWORD dwflags, DWORD dwcontext. hhttpsession - Uchwyt do sesji http. lpszverb - Metoda pobrania pliku, np. "GET" ("GET" = "NULL") // patrz RFC 2616 lpszobjectname - lpszversion - lpszreferer - lpszaccepttypes - dwflags - dwcontext - Ścieżka do pliku na serwerze. Wersja HTTP, "NULL" oznacza "HTTP/1.0. Adres URL do żądanego dokumentu. Wartość: <adres> lub NULL. Wskaźnik zawierający adres do tablicy LPCTSTR wskazującej typ zawartość danych (content types) jakie akceptuje klient. Jeżeli parametr ma wartość NULL to znaczy, że klient nie akceptuje żadnego typu danych (serwer interpretuje wartość NULL jako akceptację tylko typu "text/* ). Wartość: <adres> lub NULL. Flagi, takie same jak dla InternetOpenUrl(). Wartość definiowana przez aplikację aby zidentyfikować operacje z danymi aplikacji. An application-defined value that associates this operation with any application data. Opis : Funkcja otwiera uchwyt zapytania. Funkcja wymaga uchwytu utworzonego przez InternetConnect(). Wyjątki : Funkcja gdy nie może otworzyć sesji zwraca NULL. 20
Specyfikacja funkcji InternetReadFile() Nazwa funkcji : InternetReadFile() Zwracana wartość: BOOL Argumenty : HINTERNET hfile, LPVOID lpbuffer, DWORD dwnumberofbytestoread, LPDWORD lpnumberofbytesread hfile- Uchwyt utworzony przez HttpOpenRequest() lub InternetOpenUrl(). lpbuffer - Adres bufora (do zapisu). dwnumberofbytestoread - Liczba bajtów danych to czytania. lpnumberofbytesread - Adres zmiennej zawierającej liczbę bajtów to czytania Opis : Funkcja pobiera plik z serwera. Funkcja wymaga uchwytu utworzonego przez InternetOpenUrl() lub HttpOpenRequest(). Wyjątki : Zawraca zero (0) gdy nie może przeczytać pliku. 21
Specyfikacja funkcji InternetCloseHandle() Nazwa funkcji: InternetCloseHandle() Zwracana wartość: BOOL Zwracana wartość jest TRUE jeżeli zamknięcie uchwytu zakończyło się sukcesem, w przeciwnym przypadku zwracana jest wartość FALSE. Argumenty : HINTERNET hinet. hinet - uchwyt do zamknięcia. Opis : Funkcja zamyka uchwyt utworzony przez funkcje WinInet API. Funkcja zadeklarowana w pliku Wininet.h. Implementacja w bibliotece Wininet.lib Wymagana jest bibliteka Wininet.dll. 22
Specyfikacja funkcji HttpQueryInfo() Nazwa funkcji : HttpQueryInfo() Zwracana wartość: BOOL Argumenty : hrequest [in] dwinfolevel [in] HINTERNET hrequest, DWORD dwinfolevel, LPVOID lpbuffer, LPDWORD lpdwbufferlength, LPDWORD lpdwindex uchwyt Open HTTP request zwracany przez HttpOpenRequest() lub InternetOpen(). Specifies a combination of the attribute to query and the flags that modify the request. The following table shows the possible attribute values. lpbuffer [in, out] wskaźnik typu long void do bufora, który służy do odbierania danych (żądań HTTP). lpdwbufferlength [in, out] wskaźnik typu long do zmiennej która przechowuje długość bufora do odbierania danych. Wsakaźnik przechowuje długość stringu 1 ( znak zera zakończenia - terminating null). lpdwindex - [in, out] wskaźnik typu long do indeksu nagłówka złużącego do numerowania nagłówków o takich samych nazwach. Opis : Funkcja służy do uzysknia informacji parametrach HTTP request. 23
Internet Server API (ISAPI) Extensions Internet Server API jest zbiorem funkcji (implementowanych w bibliotekach dll) służących do zarządzania i żądania usługi indeksowania (Indexing Service) serwerów WWW IIS. 24
Odwzorowanie typów danych Generic-textdata type name SBCS (_UNICODE, _MBCS not defined) _MBCS defined (Multibyte Character Sets) _UNICODE defined _TCHAR char char wchar_t _tfinddata_t _finddata_t _finddata_t _wfinddata_t _tfinddata64_t finddata64_t finddata64_t wfinddata64_t _tfinddatai64_t _finddatai64_t _finddatai64_t _wfinddatai64_t _TINT int int wint_t _TSCHAR signed char signed char wchar_t _TUCHAR unsigned char unsigned char _TXCHAR char unsigned char _T or _TEXT No effect (removed by preprocessor) No effect (removed by preprocessor) L(converts following character or string to its Unicodecounterpart) 25
Specyfikacja projektu Nazwa projektu: httpget Typ projektu: Win32 console application Lista plików: httpget.cpp Metoda kompilacji: Microsoft Visual C++ 2008. Utworzyć projekt typu 'Win32 console application w menu (-)File-> New -> Project-> Other languages-> Visual C++ -> win32 -> Win32 console application -> wpisać nazwę: httpget -> przycisk (OK) -> Okno Win32 application wizard httpget-> wybrać: Application settings -> wybrać: Empty project-> Przycisk (Finish). Konfiguracja projektu: (-)Project-> nazwa_projektu Properies... -> Configuration Properies-> Linker-> Input -> Additional Dependecies, wpisać: WinInet.Lib. Uwaga: w pliku httpget.vcproj, atrybutowi CharacterSet tagu Configuration przypisać wartość 2, tzn. <Configuration CharacterSet="2 > Opis programu: Program pobiera metodą GET plik tekstowy z serwera WWW. Uruchomienie. W linii komend (Run-> cmd) wpisać: \>nazwa_aplikacji adres_url nazwa_pliku_do_zapisu Przykład: Z serwera www http://www.math.uni.opole.pl/ pobierany jest plik home.html i zapisywany do pliku home.html \>httpget http:///www.math.uni.opole.pl/home.html home.html 26
Struktura programu. Funkcje WinHttp. Funkcje WinInet, WinHttp: InternetOpen() InternetConnect() InternetCrackUrl() HttpOpenRequest() InternetReadFile() InternetCloseHandle() Uchwyty internetowe (internet handle): Uchwyt sesji : HINTERNET hinternet; Uchwyt do połączeń: HINTERNET hconnect; Uchwyt do zapytań : HINTERNET hhttprequest; Deklaracja obiektu SkladnikiUrla typu SKLADNIKI_URL. SKLADNIKI_URL SkladnikiUrla; // patrz: URL_COMPONENTS 27
Struktura programu. Zmienne programu. Zmienne programu: #define BUFOR_SIZE 4096 #define URL_SIZE 64 #define TIME_OUT 5000L // wielkość bufora // Max. dlugość adresu URL // time-out (w millisekundach) na połączenie i czytanie danych SKLADNIKI_URL SkladnikiUrla; char char char char scheme[url_size]; host[url_size]; path[url_size]; bufor[bufor_size]; FILE * DWORD DWORD BOOL DoPliku; TimeOutSesji; dlugosc; // argument funkcji InternetReadFile() wynikredfile; DWORD dlugoscbufora; // dlugość czytanego stringu DWORD wielkoscbufora; // wielkość bufora 28
Struktura programu. Funkcja main(). (1) Sprawdzenie wprowadzenia poprawnej ilości argumentów do funkcji main(). (2) Otwarcie sesji http. hinternet = InternetOpen(argv[0], INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); (3) Sprawdzenie czy sesja została otwarta. Czy hinternet == NULL? (4) Określenie czasu na połączenie i czytanie danych. TimeOutSesji = TIME_OUT; (5) Przekazanie i sprawdzenie parametrów sesji http. Określenie czasu na połączenie: InternetSetOption(hInternet, INTERNET_OPTION_CONNECT_TIMEOUT, (void *) &TimeOutSesji, sizeof(timeoutsesji)); Określenie czasu na czytanie danych: InternetSetOption(hInternet, INTERNET_OPTION_DATA_RECEIVE_TIMEOUT, (void *)&TimeOutSesji, sizeof(timeoutsesji)); 29
Struktura programu. Funkcja main(). (6) Określenie wartości składników URL'a SkladnikiUrla.dwStructSize = sizeof(skladnikiurla); SkladnikiUrla.lpszScheme = scheme; SkladnikiUrla.dwSchemeLength = sizeof(scheme); SkladnikiUrla.lpszHostName = host; SkladnikiUrla.dwHostNameLength = sizeof(host); SkladnikiUrla.lpszUserName = NULL; SkladnikiUrla.dwUserNameLength = 0; SkladnikiUrla.lpszPassword = NULL; SkladnikiUrla.dwPasswordLength = 0; SkladnikiUrla.lpszUrlPath = path; SkladnikiUrla.dwUrlPathLength = sizeof(path); SkladnikiUrla.lpszExtraInfo = NULL; SkladnikiUrla.dwExtraInfoLength = 0; 30
Struktura programu. Funkcja main(). (7) Podział i sprawdzenie poprawności podziału adresu URL. InternetCrackUrl(argv[1], 0, 0, &SkladnikiUrla); (8) Sprawdzenie czy składnik nscheme jest prawidłowy. SkladnikiUrla.nScheme!= INTERNET_SCHEME_HTTP; (9) Otwarcie połączenia. hconnect = InternetConnect(hInternet, host, SkladnikiUrla.nPort, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0); (10) Sprawdzenie poprawności otwarcia połączenia. Czy hconnect == NULL? (11) Żądanie pobrania strony www metodą GET. hhttprequest = HttpOpenRequest(hConnect, "GET", path, NULL, NULL, NULL, 0, 0); 31
Struktura programu. Funkcja main(). (12) Sprawdzenie poprawności żądania strony. Czy hhttprequest == NULL? (13) Wysłanie i sprawdzenie poprawności żądania pobrania strony www. HttpSendRequest(hHttpRequest, NULL, 0, NULL, 0); (14) Określenie wielkości bufora na żądaną stronę www. wielkoscbufora = sizeof(dlugoscbufora); (15) Przekazanie i sprawdzenie wielkości bufora. HttpQueryInfo(hHttpRequest, HTTP_QUERY_CONTENT_LENGTH HTTP_QUERY_FLAG_NUMBER, &dlugoscbufora, &wielkoscbufora, NULL); (16) Otwarcie i sprawdzenie poprawności otwarcia pliku do zapisu. Czy (DoPliku = fopen(argv[2], "w")) == NULL? 32
Struktura programu. Funkcja main(). (17) Zapis strony www do pliku (zapis jeżeli: dlugosc > 0 i wynikredfile!=0 ) wynikredfile = InternetReadFile(hHttpRequest, bufor, sizeof(bufor), &dlugosc); fwrite(bufor, sizeof(char), dlugosc, DoPliku); (18) Sprawdzenie czy plik jest przeczytany. Czy!wynikRedFile? (19) Zamknięcie sesji http. InternetCloseHandle(hInternet); (20) Zamknięcie pliku. fclose(dopliku); 33
#include <winsock.h> #include <wininet.h> #include <iostream> using namespace std; #define BUFFER_LENGTH 4096 // wielkosc bufora #define URL_FIELD_LENGTH 64 // Max. dlugosc adresu URL #define TIME_OUT 5000L // time-out (w millisekundach) na polaczenie i czytanie int errexit(hinternet, const char *,...); int main(int argc, char* argv[]) { HINTERNET hinternet; // uchwyt sesji (internet handle) HINTERNET hconnect; // uchwyt do polaczen HINTERNET hhttprequest; // uchwyt do zapytan URL_COMPONENTS UrlComponents; char scheme[url_field_length]; char host[url_field_length]; char path[url_field_length]; char buffer[buffer_length]; FILE * fd; DWORD optvalue; DWORD length; BOOL ret; DWORD length_buffer; // dlugosc czytanego stringu DWORD length_buffer_size; // wielkosc bufora 34
if (argc!= 3) { cout << "wpisz: " << argv[0] << " URL nzaw_pliku" << endl; return 1; } hinternet = InternetOpen(argv[0], INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); if (hinternet == NULL) { cout <<"InternetOpen() error no: " << GetLastError() << endl; return 1; } optvalue = TIME_OUT; if(!internetsetoption(hinternet, INTERNET_OPTION_CONNECT_TIMEOUT, (void *) &optvalue, sizeof(optvalue))) { errexit(hinternet, "InternetConnect() failed: %d\n", GetLastError()); return 1; } if(!internetsetoption(hinternet, INTERNET_OPTION_DATA_RECEIVE_TIMEOUT, (void *) &optvalue, sizeof(optvalue))) { errexit(hinternet, "InternetConnect() failed: %d\n", GetLastError()); return 1; } 35
UrlComponents.dwStructSize = sizeof(urlcomponents); UrlComponents.lpszScheme = scheme; UrlComponents.dwSchemeLength = sizeof(scheme); UrlComponents.lpszHostName = host; UrlComponents.dwHostNameLength = sizeof(host); UrlComponents.lpszUserName = NULL; UrlComponents.dwUserNameLength = 0; UrlComponents.lpszPassword = NULL; UrlComponents.dwPasswordLength = 0; UrlComponents.lpszUrlPath = path; UrlComponents.dwUrlPathLength = sizeof(path); UrlComponents.lpszExtraInfo = NULL; UrlComponents.dwExtraInfoLength = 0; if(!internetcrackurl(argv[1], 0, 0, &UrlComponents)) { errexit(hinternet, "InternetCrackURL() failed: %d\n", GetLastError()); return 1; } if(urlcomponents.nscheme!= INTERNET_SCHEME_HTTP) { errexit(hinternet, "wpisz: %s URL nazwa_pliku \n", argv[0]); return 1; } 36
cout <<"Pobieranie pliku: " << path << " z: " << host << endl; hconnect = InternetConnect(hInternet, host, UrlComponents.nPort, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0); if (hconnect == NULL) { errexit(hinternet, "InternetConnect() failed: %d\n", GetLastError()); return 1; } hhttprequest = HttpOpenRequest(hConnect, "GET", path, NULL, NULL, NULL, 0, 0); if (hhttprequest == NULL) { errexit(hinternet, "HttpOpenRequest() failed: %d\n", GetLastError()); return 1; } if (!HttpSendRequest(hHttpRequest, NULL, 0, NULL, 0)) { errexit(hinternet, "HttpSendRequest() failed: %d\n", GetLastError()); return 1; } length_buffer_size = sizeof(length_buffer); if(!httpqueryinfo(hhttprequest, HTTP_QUERY_CONTENT_LENGTH HTTP_QUERY_FLAG_NUMBER, &length_buffer, &length_buffer_size, NULL)) { errexit(hinternet, "HttpQueryInfo() failed: %d\n", GetLastError()); return 1; } cout << "Przeczytano bajtów: " << length_buffer << endl; 37
int err_no = 1; if ((err_no = fopen_s(&fd, argv[2], "w+"))!= 0) { errexit(hinternet, "Can't open %s", argv[2]); return 1; } do { ret = InternetReadFile(hHttpRequest, buffer, sizeof(buffer), &length); if(fwrite(buffer, sizeof(char), length, fd)!= length) { errexit(hinternet, "Write to %s failed\n", argv[2]); return 1; } } while (length > 0 && ret); if(!ret) { errexit(hinternet, "InternetReadFile() failed: %d\n", GetLastError()); return 1; } InternetCloseHandle(hInternet); fclose(fd); } // end main() 38
int errexit(hinternet hinternet, const char *format,...) { va_list args; va_start(args, format); vfprintf(stderr, format, args); va_end(args); InternetCloseHandle(hInternet); return 1; } // end errexit() 39