Soketové programovanie v C++

Soketove Programovanie V C



Programovanie zásuviek sa stalo dôležitým predmetom v oblasti počítačových sietí. Zahŕňa vytvorenie spojenia medzi dvoma uzlami, serverom a klientom, aby mohli navzájom komunikovať bez akéhokoľvek prerušenia. Server funguje ako poslucháč v komunikačnom kanáli a počúva klienta na špecifickom porte na IP adrese. Na druhej strane klient vystupuje v komunikačnom kanáli ako komunikátor. Klient kontaktuje server, aby vytvoril spojenie a nadviazal kontakt so serverom. Cieľom tohto článku je poskytnúť komplexného a podrobného sprievodcu programovaním soketov v C++, ktorý zahŕňa základy, uvádza praktické príklady a poskytuje podrobné vysvetlenie kódu.

Vytvorenie modelu klient-server

Programovanie soketov je proces, ktorý vytvára komunikačný kanál medzi serverom a klientom pomocou soketov. V nasledujúcom príklade kódu klient spustí kontakt so serverom a server je nastavený tak, aby akceptoval pripojenia klienta. Dovoľte nám pochopiť segmenty kódu servera a klienta demonštrovaním ich jadra fungovania v rámci sieťovej komunikácie. Nasleduje kód na strane servera. Pozrime sa najprv na kód a potom ho podrobne vysvetlíme bod po bode.

1. Strana servera







Kód pre serverovú stranu modelu je uvedený nižšie. Pozrime sa, čo sa deje v kóde:



#include
#include
#include
#include

použitím menný priestor std ;

#define PORT 8080
#define MAX_BUF_SIZE 1024

int Hlavná ( ) {
int ser_socket, cli_socket ;
štrukturovať sockaddr_in ser_address, cli_address ;
char buf [ MAX_BUF_SIZE ] = { 0 } ;

ak ( ( ser_socket = zásuvka ( AF_INET, SOCK_STREAM, 0 ) ) == - 1 ) {
chyba ( 'Chyba pri vytváraní zásuvky' ) ;
VÝCHOD ( EXIT_FAILURE ) ;
}

ser_address. sin_family = OF_INET ;
ser_address. sin_addr . s_addr = INADDR_ANY ;
ser_address. sin_port = htons ( PORT ) ;

ak ( viazať ( be_socket, ( štrukturovať sockaddr * ) & ser_address, veľkosť ( ser_address ) ) == - 1 ) {
chyba ( 'Zlyhanie pri viazaní' ) ;
VÝCHOD ( EXIT_FAILURE ) ;
}

ak ( počúvaj ( be_socket, 3 ) == - 1 ) {
chyba ( 'Nepodarilo sa počúvať' ) ;
VÝCHOD ( EXIT_FAILURE ) ;
}

cout << 'Server počúva na porte' << PORT << '... \n ' ;

socklen_t cli_address_len = veľkosť ( cli_address ) ;
ak ( ( cli_socket = súhlasiť ( be_socket, ( štrukturovať sockaddr * ) & cli_address, & cli_address_len ) ) == - 1 ) {
chyba ( 'Nepodarilo sa prijať' ) ;
VÝCHOD ( EXIT_FAILURE ) ;
}

čítať ( cli_socket, buf, MAX_BUF_SIZE ) ;
cout << 'Správa klienta je:' << buf << endl ;

poslať ( cli_socket, 'Správa servera' , strlen ( 'Správa servera' ) , 0 ) ;

Zavrieť ( cli_socket ) ;
Zavrieť ( ser_socket ) ;

vrátiť 0 ;
}

Uvedený príklad je kód programu C++ na strane servera. Tento kód funguje pre jednoduchý server TCP, ktorý počúva pripojenia na jednom špecifickom porte. Po úspešnom vytvorení pripojenia server dostane správu, ktorú odošle klient. Potom ho vytlačí na konzole a odošle správu s odpoveďou klientovi. Poďme pochopiť každý riadok kódu.



Program začína zahrnutím knižníc: „iostream“ pre štandardné definície vstupu/výstupu, „cstring“ pre funkcie spracovania reťazcov, „unistd.h“ na poskytovanie prístupu k API operačného systému POSIX a „arpa/inet.h“ na vykonávať operácie na internete. Príkaz „#define PORT 8080“ znamená, že definuje číslo portu 8080, na ktorom bude server počúvať. „#define MAX_BUF_SIZE 1024“ znamená maximálnu veľkosť vyrovnávacej pamäte pre prichádzajúce dáta, ktorá je 1024.





V hlavnej funkcii sú inicializované dve premenné, „ser_socket“ a „cli_socket“, ktoré reprezentujú server aj klienta. Ďalšie tri premenné, ktorými sú „sockaddr_in“, „ser_address“ a „cli_address“ typu „struct“, sú inicializované ako štruktúry adries pre server a klienta. Potom sa inicializuje vyrovnávacia pamäť s názvom „buf“, ktorá ukladá údaje pochádzajúce od klienta.

Funkcia socket() v podmienke „if“ vytvorí nový TCP socket. AF_INET označuje IPv4, SOCK_STREAM predstavuje na pripojenie orientovaný a spoľahlivý soket TCP, posledný argument, ktorým je 0, slúži na výber predvoleného protokolu TCP, INADDR_ANY akceptuje pripojenia na ľubovoľnej adrese IP a htons (PORT) konvertuje číslo portu z poradie bajtov hostiteľa do poradia bajtov siete.



Keďže je všetko správne definované, ďalším krokom je nastaviť server ako lister na danom porte a akceptovať pripojenia na ľubovoľnom sieťovom rozhraní. Soket je daný informáciou v „ser_address“ metódou bind(). Vytlačíme chybu a proces ukončíme, ak väzba zlyhá. Funkcia accept() otvára nový soket pre spojenie s klientom, zatiaľ čo funkcia listen() dáva pokyn serveru, aby čakal na prichádzajúce spojenia. Ak funkcia accept() zlyhá, vytlačí sa chybové hlásenie a funkcia sa ukončí.

Potom server prečíta správu klienta s funkciou read() do vyrovnávacej pamäte „buf“ a potom ju vytlačí do konzoly. Funkciu send() používa server na odoslanie správy ako odpoveď klientovi. Nakoniec pomocou close() server zatvorí klientovu zásuvku, čím ukončí program, takže všetky pripojenia sú správne uzavreté a neexistuje žiadna pravdepodobnosť úniku dát.

2. Strana klienta

Teraz sa pozrime, čo sa stane v klientskom modeli:

#include
#include
#include
#include

#define PORT 8080
#define SERVER_IP '127.0.0.1'

int Hlavná ( ) {
int cli_socket ;
štrukturovať sockaddr_in ser_address ;
konšt char * správu = 'Klient posiela pozdravy!' ;

ak ( ( cli_socket = zásuvka ( AF_INET, SOCK_STREAM, 0 ) ) == - 1 ) {
chyba ( 'Chyba pri vytváraní zásuvky' ) ;
VÝCHOD ( EXIT_FAILURE ) ;
}

ser_address. sin_family = OF_INET ;
ser_address. sin_port = htons ( PORT ) ;

ak ( inet_pton ( AF_INET, SERVER_IP, & ser_address. sin_addr ) <= 0 ) {
chyba ( 'Zlá adresa' ) ;
VÝCHOD ( EXIT_FAILURE ) ;
}

ak ( pripojiť ( cli_socket, ( štrukturovať sockaddr * ) & ser_address, veľkosť ( ser_address ) ) == - 1 ) {
chyba ( 'Zlyhanie pripojenia' ) ;
VÝCHOD ( EXIT_FAILURE ) ;
}
poslať ( cli_socket, mesg, strlen ( správu ) , 0 ) ;

char buf [ 1024 ] = { 0 } ;
čítať ( cli_socket, buf, veľkosť ( buf ) ) ;
std :: cout << 'Odpoveď servera: ' << buf << std :: endl ;

Zavrieť ( cli_socket ) ;
vrátiť 0 ;
}

Pozrime sa na každý riadok kódu, aby sme pochopili, ako program funguje.

Rovnaké štyri knižnice – iostream, cstring, unistd.h a arpa/inet.h – sú tiež zahrnuté na strane klienta. Číslo portu je tiež definované spolu s IP adresou lokálneho hostiteľa 127.0.0.1. Je zadaná správa, ktorá má byť doručená na server. Klient a server musia vytvoriť spojenie podľa nasledujúceho kroku:

„if ((client_socket = socket(AF_INET, SOCK_STREAM, 0)) == -1);“ vytvorí soket pre IPv4 s typom streamu a predvoleným protokolom TCP. Funkcia perror() vypíše podrobnosti o chybe, ak sa funkcii socket() nepodarí nadviazať spojenie a program ukončí.

Adresa „server_address.sin_port = htons(PORT);“ nastavuje číslo portu po prevode na sieťové poradie bajtov. Potom sa tu zobrazí ďalšie chybové hlásenie, ktorým je „Chybná adresa“, ktorá sa vytlačí, ak s adresou nie je niečo v poriadku. Vyhľadaním adresy v „serv_address“ sa klient pripojí k serveru. Ak pripojenie zlyhá, vytlačia sa podrobnosti o chybe. Funkcia send() prenesie správu na server a zabezpečí, že nebude obsahovať žiadny príznak.

Na prijatie a uloženie odpovede zo servera sa inicializuje vyrovnávacia pamäť s názvom „buf“ typu „char“. Funkcia read() načíta odpoveď servera do vyrovnávacej pamäte. Nakoniec sa odpoveď servera vytlačí do konzoly. Nakoniec sa spojenie uzavrie pomocou príkazu close() na ukončenie soketu. Nasleduje výstup z programu:

Záver

Programovanie soketov je dôležitou súčasťou sieťovej komunikácie v informatike. Umožňuje vývoj aplikácií, ktoré dokážu komunikovať cez sieť, čo umožňuje široké spektrum možností od jednoduchých architektúr klient-server až po štruktúrované distribuované systémy. Keď je soket vytvorený v programovacom kontexte, program musí nakonfigurovať jeho charakteristiky koncového bodu, ako sú protokoly, TCP alebo UDP, a sieťovú adresu, ako je IP adresa a číslo portu. Tieto zásuvky umožňujú serverom odosielať a prijímať údaje. Tento článok ukazuje praktický príklad toho, ako funguje model klient-server v programovaní soketov.