{"id":374,"date":"2010-01-21T01:32:11","date_gmt":"2010-01-21T00:32:11","guid":{"rendered":"http:\/\/netrix.org.pl\/?p=374"},"modified":"2011-02-12T02:53:11","modified_gmt":"2011-02-12T01:53:11","slug":"pobieranie-kodu-html-stron-w-c-za-pomoca-winsock2","status":"publish","type":"post","link":"https:\/\/netrix.org.pl\/index.php\/2010\/01\/21\/pobieranie-kodu-html-stron-w-c-za-pomoca-winsock2\/","title":{"rendered":"Pobieranie kodu HTML stron w C++ za pomoc\u0105 WinSock2"},"content":{"rendered":"<p>Dzisiejsza notka b\u0119dzie o tym jak pobra\u0107 kod HTML strony WWW w aplikacji C++ korzystaj\u0105c z WinSock2. <\/p>\n<p>Pierwsz\u0105 rzecz\u0105, kt\u00f3r\u0105 trzeba wiedzie\u0107 jest to w jaki spos\u00f3b robi to przegl\u0105darka internetowa. Zaczn\u0119 od tego jak wygl\u0105da typowy adres strony WWW na przyk\u0142adzie adresu do dzia\u0142u artyku\u0142\u00f3w na stronie <a href=\"http:\/\/www.gamedev.pl\/\">http:\/\/www.gamedev.pl\/<\/a>:<\/p>\n<pre lang=\"HTML\">http:\/\/www.gamedev.pl\/articles.php<\/pre>\n<p>Powy\u017cszy adres sk\u0142ada si\u0119 z kilku cz\u0119\u015bci:<\/p>\n<ul>\n<li><strong>&#8220;http:\/\/&#8221;<\/strong> &#8211; protok\u00f3\u0142 reprezentuj\u0105cy spos\u00f3b transmisji danych, dzi\u0119ki niemu przegl\u0105darka wie w jaki spos\u00f3b komunikowa\u0107 si\u0119 z serwerem oraz na jaki port wysy\u0142a\u0107 \u017c\u0105dania<\/li>\n<li><strong>&#8220;www.gamedev.pl&#8221;<\/strong> &#8211; domena na kt\u00f3r\u0105 b\u0119dzie wys\u0142ane zapytanie &#8211; podany adres jest t\u0142umaczony na adres IP przez serwer DNS<\/li>\n<li><strong>&#8220;\/articles.php&#8221;<\/strong> &#8211; adres \u017c\u0105danego plik lub \u017c\u0105danie dla serwera WWW, kt\u00f3re aplikacja wykorzystuje do stworzenia nag\u0142\u00f3wka<\/li>\n<\/ul>\n<p>Przegl\u0105darka maj\u0105c adres strony tworzy odpowiedni nag\u0142\u00f3wek, kt\u00f3ry zostaje wys\u0142any do serwera WWW. Jak ju\u017c wspomnia\u0142em adresem tego serwera jest domena zawarta w adresie WWW natomiast port jest okre\u015blany na podstawie protoko\u0142u, czyli w przypadku &#8220;http:\/\/&#8221; jest to port 80. Nag\u0142\u00f3wek HTTP powinien zawiera\u0107 nast\u0119puj\u0105ce elementy:<\/p>\n<ul>\n<li>rodzaj zapytania &#8211; w przypadku pobrania strony jest to &#8220;GET&#8221;<\/li>\n<li>adres \u017c\u0105danego pliku lub \u017c\u0105danie &#8211; to co chcemy od serwera otrzyma\u0107, najcz\u0119\u015bciej jest to adres pliku na serwerze, czyli &#8220;\/articles.php&#8221; w tym przyk\u0142adzie<\/li>\n<li>wersja protoko\u0142u &#8211; typowo HTTP\/1.1<\/li>\n<li>domena hosta<\/li>\n<\/ul>\n<p>Dodatkowo, je\u015bli jest to konieczne, mo\u017cna wys\u0142a\u0107 informacje o tym, jakiej przegl\u0105darki u\u017cywamy (UserAgent), informacje o akceptowanych plikach, kodowaniu, ciasteczkach oraz czasie trwania po\u0142\u0105czenia, wi\u0119cej mo\u017cna dowiedzie\u0107 si\u0119 z <a href=\"http:\/\/pl.wikipedia.org\/wiki\/Lista_nag%C5%82%C3%B3wk%C3%B3w_HTTP\">tej strony wiki<\/a> oraz samych nag\u0142\u00f3wk\u00f3w, kt\u00f3re wysy\u0142a przegl\u0105darka. Jako ciekawostk\u0119 mog\u0119 doda\u0107, \u017ce istnieje fajna wtyczka dla Firefoxa, kt\u00f3ra pokazuje nag\u0142\u00f3wki wysy\u0142ane przez przegl\u0105dark\u0119 &#8211; <a href=\"https:\/\/addons.mozilla.org\/en-US\/firefox\/addon\/3829\">Live HTTP headers<\/a>.<\/p>\n<p>Oto nag\u0142\u00f3wek uzyskany z pomoc\u0105 tej wtyczki podczas \u0142\u0105czenia si\u0119 do przyk\u0142adowej strony:<\/p>\n<pre line=\"1\" lang=\"text\">\r\nGET \/articles.php HTTP\/1.1\r\nHost: www.gamedev.pl\r\nUser-Agent: Mozilla\/5.0 (Windows; U; Windows NT 6.1; pl; rv:1.9.1.7) Gecko\/20091221 Firefox\/3.5.7\r\nAccept: text\/html,application\/xhtml+xml,application\/xml;q=0.9,*\/*;q=0.8\r\nAccept-Language: pl,en-us;q=0.7,en;q=0.3\r\nAccept-Encoding: gzip,deflate\r\nAccept-Charset: ISO-8859-2,utf-8;q=0.7,*;q=0.7\r\nKeep-Alive: 300\r\nConnection: keep-alive\r\n<\/pre>\n<p>Jak wida\u0107 jest on troch\u0119 d\u0142ugi (usun\u0105\u0142em informacje o ciasteczkach, nie s\u0105 tutaj potrzebne). Aby pobra\u0107 kod strony wystarcz\u0105 tak naprawd\u0119 dwie pierwsze linijki. Jednak wa\u017cn\u0105 rzecz\u0105 jest, aby po ka\u017cdej linijce wyst\u0119powa\u0142a para znak\u00f3w \\r\\n a koniec nag\u0142\u00f3wka reprezentowany by\u0142 przez dwie pary tych znak\u00f3w. W przypadku, gdy nag\u0142\u00f3wek nie b\u0119dzie zawiera\u0142 tak skonstruowanego nag\u0142\u00f3wka, serwer po prostu udrzuci zapytanie.<\/p>\n<p>Teraz pora na kod C++ z WinSock2, oto on:<\/p>\n<pre lang=\"cpp\" line=\"1\">\r\n\/\/ Usuwa zb\u0119dne definicje z nag\u0142\u00f3wka\r\n#ifndef WIN32_LEAN_AND_MEAN\r\n#define WIN32_LEAN_AND_MEAN\r\n#endif\r\n \r\n#include <winsock2.h>\r\n#include <ws2tcpip.h>\r\n#include <string>\r\n \r\n#define BUFFER_SIZE 2048\r\n#pragma comment(lib, \"ws2_32.lib\")\t\/\/ Niezb\u0119dna biblioteka\r\nusing namespace std;\r\n \r\nint main()\r\n{\r\n\t\/\/************************************************\r\n\t\/\/ Inicjalizacja WinSock2\r\n\t\/\/************************************************\r\n\tWSADATA wsaData;\r\n\tint error;\r\n\tstring answer;\r\n\tZeroMemory(&wsaData, sizeof(wsaData));\r\n \r\n\tif(FAILED(WSAStartup(MAKEWORD(2,2), &wsaData)))\t\/\/ MAKEWORD(2,2) - Wersja WinSock\r\n\t{\r\n\t\treturn 1;\r\n\t}\r\n \r\n\tchar recvBuffer[BUFFER_SIZE];\r\n\taddrinfo hint;\t\t\t\t\t\/\/ Struktura przechowuj\u0105ca dane o po\u0142\u0105czeniu\r\n\taddrinfo* wsResult;\t\t\t\t\/\/ Wska\u017anik na rezultat\r\n\tSOCKET pSocket;\t\t\t\t\t\/\/ W\u0142a\u015bciwy pSocket\r\n \r\n\tZeroMemory(recvBuffer, sizeof(recvBuffer));\r\n\tZeroMemory(&hint, sizeof(hint));\r\n\thint.ai_family = AF_UNSPEC;\t\t\/\/ Rodzaj transmisji - nieokre\u015blony\r\n\thint.ai_socktype = SOCK_STREAM;\t\/\/ Typ gniazda - strumie\u0144\r\n\twsResult = NULL;\r\n\tpSocket = INVALID_SOCKET;\r\n \r\n\t\/\/************************************************\r\n\t\/\/ Tworzenie zapytania\t\r\n\t\/\/************************************************\r\n \r\n\t\/\/ Wyci\u0105ganie informacji z adresu\r\n\tstring httpAddress = \"http:\/\/www.gamedev.pl\/articles.php\";\r\n\tstring temp = httpAddress.substr(httpAddress.find(\"http:\/\/\") + sizeof(\"http:\/\/\") - 1);\t\/\/ Tylko http:\/\/ wi\u0119c mo\u017cna wyci\u0105\u0107\r\n\tstring domain = temp.substr(0, temp.find_first_of('\/'));\t\t\t\t\t\t\t\t\/\/ Domena\r\n\tstring addressTail = temp.substr(temp.find_first_of('\/'));\t\t\t\t\t\t\t\t\/\/ \u017b\u0105danie pliku\r\n \r\n\t\/\/ Tworzenie nag\u0142\u00f3wka\r\n\ttemp = string(\"GET \") + addressTail + \" HTTP\/1.1\\r\\n\"\r\n\t\t\t   + \"Host: \" + domain + \"\\r\\n\"\r\n\t\t\t   \/\/+ \"User-Agent: Mozilla\/5.0 (Windows; U; Windows NT 5.1; pl; rv:1.9.1.5) Gecko\/20091102 Firefox\/3.5.5\\r\\n\"\r\n\t\t\t   \/\/+ \"Accept: text\/html,application\/xhtml+xml,application\/xml;q=0.9,*\/*;q=0.8\\r\\n\"\r\n\t\t\t   \/\/+ \"Accept-Language: pl,en-us;q=0.7,en;q=0.3\\r\\n\"\r\n\t\t\t   \/\/+ \"Accept-Encoding: gzip,deflate\\r\\n\"\r\n\t\t\t   \/\/+ \"Accept-Charset: ISO-8859-2,utf-8;q=0.7,*;q=0.7\\r\\n\"\r\n\t\t\t   \/\/+ \"Keep-Alive: 300\\r\\n\"\r\n\t\t\t   \/\/+ \"Connection: keep-alive\\r\\n\"\r\n\t\t\t   + \"\\r\\n\\r\\n\";\r\n \r\n\t\/\/ Pobieranie IP serwera z serwera DNS\r\n\tif(FAILED(getaddrinfo(domain.c_str(), TEXT(\"80\"), &hint, &wsResult)))\r\n\t{\r\n\t\tprintf(\"Nie udalo sie pobrac IP\\n\");\r\n\t\treturn 1;\r\n\t}\r\n \r\n\t\/\/ Wska\u017anik na zwr\u00f3cone adresy\r\n\taddrinfo* ptr = wsResult;\r\n \r\n\t\/\/ Tworzenie socketu\r\n\tif(FAILED(pSocket = socket(wsResult->ai_family, wsResult->ai_socktype, wsResult->ai_protocol))) \r\n\t{\r\n\t\tfreeaddrinfo(wsResult);\r\n\t\tprintf(\"Nie uda\u0142o si\u0119 utworzyc socketu\\n\");\r\n\t\treturn 1;\r\n\t}\r\n \r\n\t\/\/************************************************\r\n\t\/\/ Wysy\u0142anie zapytania\t\r\n\t\/\/************************************************\r\n \r\n\t\/\/ \u0141\u0105czenie si\u0119 do serwera\r\n\tif(FAILED(connect(pSocket, ptr->ai_addr, (int)ptr->ai_addrlen))) \r\n\t{\r\n\t\tprintf(\"Nie udalo sie polaczyc do serwera\\n\");\r\n\t\tgoto Error;\r\n\t}\r\n \r\n\t\/\/ Wysy\u0142anie nag\u0142\u00f3wka\r\n\tif(FAILED(send(pSocket, temp.c_str(), temp.size(), 0)))\r\n\t{\r\n\t\tprintf(\"Nie udalo sie wyslac naglowka\\n\");\r\n\t\tgoto Error;\r\n\t}\r\n \r\n\t\/\/ Ko\u0144czenie wysy\u0142ania\r\n\tif(FAILED(shutdown(pSocket, SD_SEND)))\r\n\t{\r\n\t\tprintf(\"Nie udalo sie zamknac polaczenia\\n\");\r\n\t\tgoto Error;\r\n\t}\r\n \r\n\t\/\/************************************************\r\n\t\/\/ Odbieranie danych\r\n\t\/\/************************************************\r\n \r\n\t\/\/ Odbieranie danych\r\n\tdo\r\n\t{\r\n\t\tZeroMemory(recvBuffer, sizeof(recvBuffer));\r\n\t\terror = recv(pSocket, recvBuffer, sizeof(recvBuffer), 0);\r\n \r\n\t\tif(error > 0)\r\n\t\t{\r\n\t\t\tanswer += string(recvBuffer);\r\n\t\t}\r\n\t}\r\n\twhile(error > 0);\r\n \r\n\tclosesocket(pSocket);\t\t\/\/ Zamkni\u0119cie socketu\r\n\tfreeaddrinfo(wsResult);\t\t\/\/ oraz zwolnienie struktury addrinfo\r\n \r\n\tprintf(\"Kod HTML strony \\\"http:\/\/www.gamedev.pl\/articles.php\\\":\\n\\n%s\", answer.c_str());\r\n\treturn 0;\r\n \r\nError:\r\n\tclosesocket(pSocket);\r\n\tfreeaddrinfo(wsResult);\r\n\treturn 1;\r\n}\r\n<\/pre>\n<p>Wynikiem tego kodu jest wy\u015bwietlony kod HTML przyk\u0142adowej strony.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Dzisiejsza notka b\u0119dzie o tym jak pobra\u0107 kod HTML strony WWW w aplikacji C++ korzystaj\u0105c z WinSock2. Pierwsz\u0105 rzecz\u0105, kt\u00f3r\u0105 trzeba wiedzie\u0107 jest to w jaki spos\u00f3b robi to przegl\u0105darka internetowa. Zaczn\u0119 od tego jak wygl\u0105da typowy adres strony WWW na przyk\u0142adzie adresu do dzia\u0142u artyku\u0142\u00f3w na stronie http:\/\/www.gamedev.pl\/: http:\/\/www.gamedev.pl\/articles.php Powy\u017cszy adres sk\u0142ada si\u0119 z [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[12],"tags":[179,103],"_links":{"self":[{"href":"https:\/\/netrix.org.pl\/index.php\/wp-json\/wp\/v2\/posts\/374"}],"collection":[{"href":"https:\/\/netrix.org.pl\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/netrix.org.pl\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/netrix.org.pl\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/netrix.org.pl\/index.php\/wp-json\/wp\/v2\/comments?post=374"}],"version-history":[{"count":33,"href":"https:\/\/netrix.org.pl\/index.php\/wp-json\/wp\/v2\/posts\/374\/revisions"}],"predecessor-version":[{"id":1343,"href":"https:\/\/netrix.org.pl\/index.php\/wp-json\/wp\/v2\/posts\/374\/revisions\/1343"}],"wp:attachment":[{"href":"https:\/\/netrix.org.pl\/index.php\/wp-json\/wp\/v2\/media?parent=374"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/netrix.org.pl\/index.php\/wp-json\/wp\/v2\/categories?post=374"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/netrix.org.pl\/index.php\/wp-json\/wp\/v2\/tags?post=374"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}