Programiranje vtičnic v C++

Programiranje Vticnic V C



Programiranje vtičnic je postalo pomemben predmet na področju računalniških omrežij. Vključuje vzpostavitev povezave med dvema vozliščema, strežnikom in odjemalcem za medsebojno komunikacijo brez kakršnih koli prekinitev. Strežnik deluje kot poslušalec v komunikacijskem kanalu in posluša odjemalca na določenih vratih na naslovu IP. Po drugi strani pa naročnik nastopa kot komunikator v komunikacijskem kanalu. Odjemalec stopi v stik s strežnikom, da ustvari povezavo in vzpostavi stik s strežnikom. Namen tega članka je zagotoviti izčrpen in podroben vodnik za programiranje vtičnic v C++, ki pokriva osnove, predstavlja praktične primere in nudi podrobno razlago kode.

Vzpostavitev modela odjemalec-strežnik

Programiranje vtičnic je proces, ki gradi komunikacijski kanal med strežnikom in odjemalcem z uporabo vtičnic. V naslednjem primeru kode odjemalec vzpostavi stik s strežnikom in strežnik je nastavljen tako, da sprejme povezave odjemalca. Dovolite nam, da razumemo segmente kode strežnika in odjemalca s prikazom njihovega jedra, ki deluje znotraj omrežne komunikacije. Sledi koda na strani strežnika. Najprej si oglejmo kodo in nato podrobno razložimo kodo, točko za točko.

1. Strežniška stran







Koda za strežniško stran modela je podana v nadaljevanju. Poglejmo, kaj se dogaja v kodi:



#include
#include
#include
#include

uporabo imenski prostor std ;

#define PORT 8080
#define MAX_BUF_SIZE 1024

int glavni ( ) {
int ser_socket, cli_socket ;
struct sockaddr_in ser_address, cli_address ;
char buf [ MAX_BUF_SIZE ] = { 0 } ;

če ( ( ser_socket = vtičnica ( AF_INET, SOCK_STREAM, 0 ) ) == - 1 ) {
groza ( 'Napaka pri ustvarjanju vtičnice' ) ;
izhod ( EXIT_FAILURE ) ;
}

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

če ( vezati ( be_socket, ( struct sockaddr * ) & ser_address, sizeof ( ser_address ) ) == - 1 ) {
groza ( 'Napaka v vezavi' ) ;
izhod ( EXIT_FAILURE ) ;
}

če ( poslušaj ( be_socket, 3 ) == - 1 ) {
groza ( 'Ni uspelo poslušati' ) ;
izhod ( EXIT_FAILURE ) ;
}

cout << 'Strežnik posluša na vratih' << PORT << '... \n ' ;

socklen_t cli_address_len = sizeof ( cli_naslov ) ;
če ( ( cli_socket = sprejeti ( be_socket, ( struct sockaddr * ) & cli_address, & cli_address_len ) ) == - 1 ) {
groza ( 'Ni bilo mogoče sprejeti' ) ;
izhod ( EXIT_FAILURE ) ;
}

prebrati ( cli_socket, buf, MAX_BUF_SIZE ) ;
cout << 'Sporočilo stranke je: ' << buf << konec ;

poslati ( cli_socket, 'Sporočilo strežnika' , strlen ( 'Sporočilo strežnika' ) , 0 ) ;

blizu ( cli_socket ) ;
blizu ( ser_socket ) ;

vrnitev 0 ;
}

Navedeni primer je strežniška koda programa C++. Ta koda deluje za preprost strežnik TCP za poslušanje povezav na posameznih specifičnih vratih. Ko je povezava uspešno ustvarjena, bo strežnik prejel sporočilo, ki ga pošlje odjemalec. Nato ga natisne na konzolo in odjemalcu pošlje odgovor. Razumejmo vsako vrstico kode.



Program se začne z vključitvijo knjižnic: »iostream« za standardne vhodno/izhodne definicije, »cstring« za funkcije za obdelavo nizov, »unistd.h« za zagotavljanje dostopa do API-ja operacijskega sistema POSIX in »arpa/inet.h« za izvajati internetne operacije. Izjava “#define PORT 8080” pomeni, da definira številko vrat 8080, na katerih bo strežnik poslušal. “#define MAX_BUF_SIZE 1024” pomeni največjo velikost medpomnilnika za vhodne podatke, ki je 1024.





V glavni funkciji sta inicializirani dve spremenljivki, 'ser_socket' in 'cli_socket', ki predstavljata strežnik in odjemalca. Druge tri spremenljivke, ki so 'sockaddr_in', 'ser_address' in 'cli_address' tipa 'struct', so inicializirane kot strukture naslovov za strežnik in odjemalca. Po tem se inicializira medpomnilnik z imenom 'buf', ki shrani podatke, ki prihajajo od odjemalca.

Funkcija socket() v pogoju »if« ustvari novo vtičnico TCP. AF_INET označuje IPv4, SOCK_STREAM predstavlja povezovalno usmerjeno in zanesljivo vtičnico TCP, zadnji argument, ki je 0, je podan za izbiro privzetega protokola TCP, INADDR_ANY sprejema povezave na katerem koli naslovu IP, htons (PORT) pa pretvori številko vrat iz gostiteljski vrstni red bajtov v omrežni vrstni red bajtov.



Ker je vse pravilno definirano, je naslednji korak nastavitev strežnika kot seznama na danih vratih in sprejemanje povezav na katerem koli omrežnem vmesniku. Vtičnica je podana z informacijami v “ser_address” z metodo bind(). Izpišemo napako in zaključimo postopek, če vezava ne uspe. Funkcija accept() odpre novo vtičnico za povezavo z odjemalcem, medtem ko funkcija listen() naroči strežniku, naj počaka na dohodne povezave. Če funkcija accept() ne uspe, se natisne sporočilo o napaki in funkcija se bo zaprla.

Nato strežnik prebere sporočilo odjemalca s funkcijo read() v medpomnilnik »buf« in ga nato natisne na konzolo. Funkcijo send() uporablja strežnik za pošiljanje sporočila kot odgovor odjemalcu. Nazadnje strežnik z uporabo close() zapre odjemalčevo vtičnico in prekine program, tako da so vse povezave pravilno zaprte in ni možnosti kršitve podatkov.

2. Stran odjemalca

Zdaj pa poglejmo, kaj se zgodi v modelu odjemalca:

#include
#include
#include
#include

#define PORT 8080
#define SERVER_IP '127.0.0.1'

int glavni ( ) {
int cli_socket ;
struct sockaddr_in ser_address ;
konst char * sporočilo = 'Stranka pošilja pozdrave!' ;

če ( ( cli_socket = vtičnica ( AF_INET, SOCK_STREAM, 0 ) ) == - 1 ) {
groza ( 'Napaka pri ustvarjanju vtičnice' ) ;
izhod ( EXIT_FAILURE ) ;
}

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

če ( inet_pton ( AF_INET, SERVER_IP, & ser_address. sin_addr ) <= 0 ) {
groza ( 'Napačen naslov' ) ;
izhod ( EXIT_FAILURE ) ;
}

če ( povezati ( cli_socket, ( struct sockaddr * ) & ser_address, sizeof ( ser_address ) ) == - 1 ) {
groza ( 'Napaka povezave' ) ;
izhod ( EXIT_FAILURE ) ;
}
poslati ( cli_socket, sporočilo, strlen ( sporočilo ) , 0 ) ;

char buf [ 1024 ] = { 0 } ;
prebrati ( cli_socket, buf, sizeof ( buf ) ) ;
std :: cout << 'Odziv strežnika: ' << buf << std :: konec ;

blizu ( cli_socket ) ;
vrnitev 0 ;
}

Oglejmo si vsako vrstico kode, da bomo razumeli, kako program deluje.

Iste štiri knjižnice – iostream, cstring, unistd.h in arpa/inet.h – so vključene tudi na strani odjemalca. Številka vrat je prav tako definirana skupaj z naslovom IP lokalnega gostitelja 127.0.0.1. Podano je sporočilo, ki ga je treba dostaviti strežniku. Odjemalec in strežnik morata vzpostaviti povezavo v naslednjem koraku:

»if ((client_socket = socket(AF_INET, SOCK_STREAM, 0)) == -1);« ustvari vtičnico za IPv4 z vrsto toka in privzetim protokolom TCP. perror() natisne podrobnosti o napaki, če funkcija socket() ne vzpostavi povezave in zapusti program.

»server_address.sin_port = htons(PORT);« nastavi številko vrat po pretvorbi v omrežni vrstni red bajtov. Nato se tukaj prikaže drugo sporočilo o napaki, ki je »Napačen naslov« in se natisne, če je z naslovom kaj narobe. Z iskanjem naslova v “ser_address” se odjemalec poveže s strežnikom. Če povezava ne uspe, se natisnejo podrobnosti o napaki. Funkcija send() bo sporočilo prenesla na strežnik in zagotovila, da ne vsebuje nobene zastavice.

Za sprejem in shranjevanje odgovora s strežnika se inicializira medpomnilnik z imenom 'buf' tipa 'char'. Funkcija read() prebere odgovor strežnika v medpomnilnik. Nazadnje se odgovor strežnika natisne na konzolo. Končno se povezava zapre s stavkom close() za prekinitev vtičnice. Sledi rezultat programa:

Zaključek

Programiranje vtičnic je pomemben del omrežne komunikacije v računalništvu. Omogoča razvoj aplikacij, ki lahko komunicirajo prek omrežja, kar omogoča široko paleto možnosti od preprostih arhitektur odjemalec-strežnik do strukturiranih porazdeljenih sistemov. Ko je vtičnica ustvarjena v kontekstu programiranja, mora program konfigurirati njene značilnosti končne točke, kot so protokoli, TCP ali UDP, in omrežni naslov, kot sta naslov IP in številka vrat. Te vtičnice omogočajo strežnikom pošiljanje in prejemanje podatkov. Ta članek prikazuje praktičen primer delovanja modela odjemalec-strežnik v programiranju vtičnic.