IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

HTTP klient pomocou BSD socketov

Jedná sa o prvý školský projekt v rámci predmetu počítačovej siete. Zadaním bolo vytvoriť jednoduchý HTTP klient v C / C ++ as použitím BSD socketov.

Východiskovým textom k implementácii bolo toto RFC, ktoré som však rozhodne nemal čas prečítať celé. Implementoval som len nutné minimum (redirect, chunked prenos, základné stavové kódy) pre funkčného HTTP klienta.

S implementáciou som začal v deň odovzdávania, takže sa prosím nikto neinspirujte štýlom kódu (všetko v main, divná kombinácia C a C ++). Musím sa ale pochváliť svojím prvým použitím goto (okrem assemblery) ..: D

Použitie programu je jednoduché. Pri svojom spustení očakáva jediný parameter - platnú url. Podporuje aj iné porty, ako predvolené.

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

Ak by chcel niekto tento program vyskúšať na Windows, tak je to možné s použitím Cygwin, ktorý implementuje sys / socket.ha alebo je možné program portovať na WinSocks. Sú tam drobné rozdiely, ale nič zásadné.

BSD Sockety

BSD (alebo tiež Berkley) sockety sú Unixové API (nájdete ich teda natívne v Linuxe alebo BSD) pre medziprocesorovej a internetovú komunikáciu. Ich zmyslom je obaliť systémové implementácie jednotlivých protokolov (tj. IPv4, IPv6, TCP, UDP, ...) rôznych úrovní a vytvoriť jednotné rozhranie. Vznikli už roku 1983 a boli natoľko úspešné, že sú de facto používané vo všetkých moderných OS. Windows je implementuje mierne odlišne (už spomínané WinSocks) a v praxi sa odporúča používať POSIX sockety, ktoré nahradzujú staršie BSD funkcie (gethostbyname, gethostbyaddr, ...) za moderné (príjemnejšie sa programujú a vie niektoré veci navyše) gettaddrinfo a getnameinfo.

Tento projekt ukazuje použitie pôvodných BSD socketov (testovaný bol na FreeBSD 10.2, ale funguje aj na modernom Linuxe) a IPv4 / TCP stacku.

Základný princíp

Využitie BSD socketov je v zásade veľmi jednoduché. Najprv vytvoríme tzv. Socket - z pohľadu programátora ide de facto o "obyčajný súbor" a môžeme s ním pracovať veľmi podobne. Keď do neho zapíšeme, systém úplne autonómne vezme dáta, vytvorí z nich pakety (v tomto prípade TCP) a odošle ich. Vďaka použitiu TCP je zaručené správne poradie doručených dát a tiež ich bezchybnosť.

Vytvorenie socketu je triviálne. Definujeme, ktoré protokoly budú využité. AF_INET značí IPv4 a SOCK_STREAM TCP:

tcp_socket = socket(AF_INET, SOCK_STREAM, 0);

Ďalší krok je opäť jednoduchý. Je potrebné získať IP adresu servera z jeho mena (DNS záznamu). K tomu môžeme využiť gethostbyname ().

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

Zo štruktúry hostent potom získame všetky dôležité informácie. Tento krok je trochu neprehľadný a pri použití spomínaných POSIX socketov (tie som využil v druhom projekte) 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

Ďalším krokom je už pripojenie na server:

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

Teraz, keď máme nadviazané TCP spojenia, môžeme jednoducho odosielať a prijímať dáta ..

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);

Ak vám vŕtala hlavou tá nula ako posledný parameter všetkých volaní, tak ide o flags - môžete modifikovať správanie (možnosti viď. Manuálové stránky). V tomto prípade napríklad bude program čakať, až bude prijaté presne chunk_size bajtov a až potom ich vráti.

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

Na záver po sebe ako slušní programátori upraceme:

close(tcp_socket);

Záver

Program je len veľmi jednoduchá ukážka, ako vytvoriť aplikáciu komunikujúce po sieti. Nabudúce ukážem, ako vytvoriť server a vlastné jednoduchý protokol pre prenos súborov.


Galéria


 

Stiahnuť

Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami

Stiahnuté 44x (3.5 kB)
Aplikácia je vrátane zdrojových kódov v jazyku C

 

Všetky články v sekcii
Zdrojákoviště jazyka C - Programovanie v Linuxe
Program pre vás napísal David Novák
Avatar
Užívateľské hodnotenie:
Ešte nikto nehodnotil, buď prvý!
Autor se zajímá především o nízkoúrovňové programování (C/C++, ASM) a návrh hardwaru (VHDL).
Aktivity