HTTP klient pomocí BSD socketů

C++ Linux HTTP klient pomocí BSD socketů

Jedná se o první školní projekt v rámci předmětu počítačové sítě. Zadáním bylo vytvořit jednoduchý HTTP klient v C/C++ a s použitím BSD socketů.

Výchozím textem k implementaci bylo toto RFC, které jsem ovšem rozhodně neměl čas přečíst celé. Implementoval jsem jen nutné minimum (redirect, chunked přenos, základní stavové kódy) pro funkčního HTTP klienta.

S implementací jsem začal v den odevzdávání, takže se prosím nikdo neinspirujte stylem kódu (vše v main, divná kombinace C a C++). Musím se ale pochlubit svým prvním použitím goto (mimo asembler).. :D

Použití programu je jednoduché. Při svém spuštění očekává jediný parametr - platnou url. Podporuje i jiné porty, než výchozí.

$ webclient www.abcd.cz:88/cesta/test.html

Pokud by chtěl někdo tento program vyzkoušet na Windows, tak je to možné s použitím Cygwin, který implementuje sys/socket.h a nebo je možné program portovat na WinSocks. Jsou tam drobné rozdíly, ale nic zásadního.

BSD Sockety

BSD (nebo také Berkley) sockety jsou Unixové API (najdete je tedy nativně v Linuxu nebo BSD) pro meziprocesovou a internetovou komunikaci. Jejich smyslem je obalit systémové implementace jednotlivých protokolů (tj. IPv4, IPv6, TCP, UDP, ...) různých úrovní a vytvořit jednotné rozhraní. Vznikly již roku 1983 a byly natolik úspěšné, že jsou de facto používány ve všech moderních OS. Windows je implementuje mírně odlišně (již zmíněné WinSocks) a v praxi se doporučuje používat POSIX sockety, které nahrazují starší BSD funkce (gethostbyname, gethostbyaddr, ...) za moderní (příjemněji se programují a umí některé věci navíc) gettaddrinfo a getnameinfo.

Tento projekt ukazuje použití původních BSD socketů (testován byl na FreeBSD 10.2, ale funguje i na moderním Linuxu) a IPv4/TCP stacku.

Základní princip

Využití BSD socketů je v zásadě velmi jednoduché. Nejprve vytvoříme tzv. socket - z pohledu programátora jde de facto o "obyčejný soubor" a můžeme s ním pracovat velmi podobně. Když do něj zapíšeme, systém naprosto autonomně vezme data, vytvoří z nich pakety (v tomto případě TCP) a odešle je. Díky použití TCP je zaručeno správné pořadí doručených dat a také jejich bezchybnost.

Vytvoření socketu je triviální. Definujeme, které protokoly budou využity. AF_INET značí IPv4 a SOCK_STREAM TCP:

tcp_socket = socket(AF_INET, SOCK_STREAM, 0);

Další krok je opět jednoduchý. Je třeba získat IP adresu serveru z jeho jména (DNS záznamu). K tomu můžeme využít gethostbyname().

struct hostent *server;
server = gethostbyname(hostname.c_str());  // očekává klasický C string

Ze struktury hostent pak získáme všechny důležité informace. Tento krok je poněkud neprůhledný a při použití zmíněných POSIX socketů (ty jsem využil v druhém projektu) odpadá.

struct sockaddr_in server_address;
memset(&server_address, 0, sizeof(server_address));  // vymazání struktury
server_address.sin_family = AF_INET;  // nastavení IPv4
memcpy(&server_address.sin_addr.s_addr, server->h_addr_list[0], server->h_length);  // nakopírování samotné adresy
server_address.sin_port = htons(port);  // htons: převod do big-endian

Dalším krokem je již připojení k serveru:

connect(tcp_socket, (const struct sockaddr *) &server_address, sizeof(server_address));

Teď, když máme navázáno TCP spojení, můžeme jednoduše odesílat a přijímat data..

string http_get = "nejaky text podle HTTP standardu..";
int reply_size;
char reply[BUFFER_LEN];

send(tcp_socket, http_get.c_str(), http_get.size(), 0);
reply_size = recv(tcp_socket, reply, BUFFER_LEN, 0);

Pokud vám vrtala hlavou ta nula jako poslední parametr všech volání, tak jde o flags - můžete modifikovat chování (možnosti viz. manuálové stránky). V tomto případě například bude program čekat, až bude přijato přesně chunk_size bajtů a až pak je vrátí.

reply_size = recv(tcp_socket, reply, chunk_size, MSG_WAITALL);

Na závěr po sobě jakožto slušní programátoři uklidíme:

close(tcp_socket);

Závěr

Program je jen velmi jednoduchá ukázka, jak vytvořit aplikaci komunikující po síti. Příště ukážu, jak vytvořit server a vlastní jednoduchý protokol pro přenos souborů.


Galerie

Program byl vytvořen v roce 2016.

 

Stáhnout

Staženo 7x (3.5 kB)
Aplikace je včetně zdrojových kódů v jazyce C

 

  Aktivity (2)

Program pro vás napsal David Novák
Avatar
Autor v současné době studuje FIT VUT Brno a zajímá se především o nízkoúrovňové programování (C/C++, ASM) a návrh hardwaru (VHDL). Je zde také členem výzkumného týmu ANT@FIT (Accelerated Network Technologies).

Jak se ti líbí článek?
Celkem (2 hlasů) :
4.54.54.54.54.5


 


Miniatura
Všechny články v sekci
Programování v jazyce C v Linuxu

 

 

Komentáře

Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zatím nikdo nevložil komentář - buď první!