| Aktualnie online |
Go¶ci online: 1
U¿ytkowników online: 1
Magnefikko
£±cznie u¿ytkowników: 56
Najnowszy u¿ytkownik: KangurX
|
|
| Informacje |
Posty na forum: 2711 Tematy na forum: 133 Artyku³y: 65 Komentarze: 125 Oceny: 68
|
|
| Hosting |
|
|
|
| [C++] Pobieranie strony internetowej |
Dobry ;)
W dzisiejszym odcinku zajmiemy siê pobieraniem zawarto¶ci strony internetowej metod± GET dziêki programowi napisanemu w C++. Jako interfejs pos³u¿± nam sockety (Linux)/winsock (Windows).
1. Request - co i jak?
Request to po prostu ¿±danie wys³ane przez przegl±darkê serwerowi http. Przyk³adowy request:
GET /axe/news.php HTTP/1.1
Host: promhyl.netne.net
Naszym zadaniem jest wys³aæ w³a¶nie takie ¿±danie podanemu serwerowi http.
Zatem bierzmy siê do roboty.
Ma³a uwaga co do ¿±dania: ka¿da linia koñczy siê znakami \r\n. Ostatnia zawiera dwie takie kombinacje, aby serwer wiedzia³ gdzie koñczy siê request.
2. Kod.
Kod bêdzie dla Windowsa jak i dla Linuksa. Jako, ¿e ró¿nic wielu nie ma pos³u¿ymy siê instrukcjami preprocesora, aby kompilator wybra³ odpowiedni kod. Dla uproszczenia napiszemy sobie ma³± klasê odpowiadaj±c± za zarz±dzanie urlem.
// getwww.cpp
// Kompilacja:
// Linux:
// g++ getwww.cpp -o getwww
// Windows:
// g++ getwww.cpp -o getwww -lws2_32
// Tutaj definiujemy symbol, który pos³u¿y kompilatorowi do wybrania
// odpowiednich nag³ówków. Wystarczy jeden sybmol. Jako, ¿e piszê pod Linuksem
// zostawiê go zakomentowanego. Je¶li kto¶ pisze pod Windowsem, nale¿y go
// odkomentowaæ.
// #define WINDOWS
#include < iostream>
#include < fstream>
#include < ctime>
#include "url.cpp"
// Nag³ówki dla Windowsa
#ifdef WINDOWS
#include < winsock2.h>
// Nag³ówki dla Linuksa
#else
#include < sys/socket.h>
#include < sys/stat.h>
#include < netinet/in.h>
#include < arpa/inet.h>
#include < netdb.h>
// Przera¿aj±ce nie? xD
// W cale nie. Wystarczy w manualu wpisaæ i od razu podane gdzie to jest.
#endif
using namespace std;
// Prototypy //////////////////////////////////////////////////////////////////
void usage(const char* progname);
void wait(unsigned int sec);
// MAIN ///////////////////////////////////////////////////////////////////////
int main(int argc, char* argv[])
{
// Argumenty:
// argv[0] - nazwa programu
// argv[1] - url
// argv[2] - plik wynikowy
if (argc != 3)
{
usage(argv[0]);
return 0;
}
Url url(argv[1]);
if (!url.isValid())
{
cout << "Podany url jest nieprawidlowy!\n";
return -1;
}
cout << "Url: " << url.getUrl() << endl;
cout << "Www: " << url.getWww() << endl;
cout << "Host: " << url.getHost() << endl;
cout << "File: " << url.getFile() << endl;
ofstream file(argv[2]);
if (!file)
{
cout << "Nie mozna otworzyc pliku do zapisu!\n";
return -1;
}
// Je¶li jeste¶my pod Windowsem - inicjalizujemy WinSocka
#ifdef WINDOWS
WSAData wd;
if (WSAStartup(MAKEWORD(2,0), &wd) == SOCKET_ERROR)
{
cout << "Nie udalo sie zainicjalizowac biblioteki WinSock!\n";
return -1;
}
#endif
// Tworzymy socketa
int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
// Pobieramy adres hosta
hostent* host = gethostbyname(url.getHost());
if (!host)
{
cout << "Nie odnaleziono podanego hosta!\n";
return -1;
}
sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(80);
addr.sin_addr = *(in_addr*)host->h_addr;
cout << "IP serwera: " << inet_ntoa(addr.sin_addr) << endl;
// £±czymy z serwerem
if (connect(sock, (sockaddr*)&addr, sizeof(addr)) == -1)
{
cout << "Nie udalo sie nawiazac polaczenia z serwerem!\n";
return -1;
}
// ¦lemy requesta
string request = "GET ";
request += url.getFile();
request += " HTTP/1.1\r\nHost: ";
request += url.getWww();
request += "\r\n\r\n";
cout << "Request: " << request;
send(sock, request.c_str(), request.length(), 0);
// Odbieramy odpowied¼.
char buffer[8192];
int size;
do
{
wait(2); // Czekamy, aby wszystkie dane nap³ynê³y.
size = recv(sock, buffer, sizeof(buffer), 0);
cout << "Odebrano " << size << " B danych.\n";
file.write(buffer, size);
}while (size == sizeof(buffer));
file.close();
close(sock); // Zamykamy po³±czenie
#ifdef WINDOWS
WSACleanup();
#endif
cout << "Zakonczono.\n";
return 0;
}
// usage //////////////////////////////////////////////////////////////////////
void usage(const char* progname)
{
cout << "Uzycie:\n";
cout << "\t\t" << progname << " \n\n";
cout << "\tadres url - adres do strony, ktora chcesz pobrac \n\t\t(np. http://www.promhyl.netne.net/)\n";
cout << "\tplik wynikowy - do tego pliku zostanie zapisana pobrana strona\n\n";
}
// wait ///////////////////////////////////////////////////////////////////////
void wait(unsigned int sec)
{
// Ta funkcja s³u¿y do opó¼nienia odbioru danych od serwera, aby wszystkie mog³y nap³yn±æ do socketa.
time_t a = time(NULL) + sec;
while (a > time(NULL));
}
Pliki url.h i url.cpp do³±czone s± do archiwum z kodem. My¶lê, ¿e wszystko jest dobrze obkomentowane ;)
Program ten ma kilka s³abo¶ci, m.in. czas wyznaczony na doj¶cie danych mo¿e siê wyd³u¿yæ, program nie ucina nag³ówków itp., ale dzia³a jak nale¿y ;)
3. Materia³y do pobrania.
Kompletny kod, oraz skompilowany program (pod Linuksem) - tutaj.
4. Epilog.
No to by by³o na tyle. Pozdrowienia dla Promhyl Studies, a w szczególno¶ci dla Widma ;P
Pozdrawiam
Sinis
|
|
| Dodaj komentarz |
|
Zaloguj siê, aby móc dodaæ komentarz.
|
|
|
| Shoutbox |
Musisz zalogowaæ siê, aby móc dodaæ wiadomo¶æ.
|
|
|