Socket-programmering i C++

Socket Programmering I C



Socket-programmering har blitt et viktig fag innen datanettverk. Det innebærer å etablere en forbindelse mellom to noder, server og klient for å kommunisere med hverandre uten avbrudd. Serveren fungerer som en lytter i kommunikasjonskanalen og lytter til klienten på en bestemt port på en IP-adresse. På den annen side fungerer klienten som en kommunikator i kommunikasjonskanalen. Klienten kontakter serveren for å opprette en forbindelse og ta kontakt med serveren. Denne artikkelen tar sikte på å gi en omfattende og detaljert veiledning til socket-programmering i C++, som dekker det grunnleggende, presenterer praktiske eksempler og gir en detaljert forklaring av koden.

Etablering av klient-servermodellen

Socket-programmering er prosessen som bygger en kommunikasjonskanal mellom serveren og klienten ved hjelp av sockets. I følgende eksempelkode starter klienten en kontakt med serveren, og serveren er satt opp til å akseptere klienttilkoblingene. La oss forstå server- og klientkodesegmentene ved å demonstrere deres kjernearbeid innenfor nettverkskommunikasjonen. Følgende er koden på serversiden. La oss først se koden og deretter forklare koden i detalj, punkt for punkt.

1. Serverside







Koden for serversiden av modellen er gitt i det følgende. La oss se hva som skjer i koden:



#include
#include
#include
#include

ved hjelp av navneområde std ;

#define PORT 8080
#define MAX_BUF_SIZE 1024

int hoved- ( ) {
int ser_socket, cli_socket ;
struktur sockaddr_in ser_address, cli_address ;
røye buff [ MAX_BUF_SIZE ] = { 0 } ;

hvis ( ( ser_socket = stikkontakt ( AF_INET, SOCK_STREAM, 0 ) ) == - 1 ) {
feil ( 'Feil ved oppretting av Socket' ) ;
exit ( EXIT_FAILURE ) ;
}

ser_adresse. sin_familie = OF_INET ;
ser_adresse. sin_addr . s_addr = INADDR_ANY ;
ser_adresse. sin_port = htons ( HAVN ) ;

hvis ( binde ( be_socket, ( struktur sockaddr * ) & ser_adresse, størrelsen av ( ser_adresse ) ) == - 1 ) {
feil ( 'Feil i binding' ) ;
exit ( EXIT_FAILURE ) ;
}

hvis ( lytte ( be_socket, 3 ) == - 1 ) {
feil ( 'Kunne ikke lytte' ) ;
exit ( EXIT_FAILURE ) ;
}

cout << 'Server lytter på port' << HAVN << '... \n ' ;

socklen_t cli_address_len = størrelsen av ( cli_adresse ) ;
hvis ( ( cli_socket = aksepterer ( be_socket, ( struktur sockaddr * ) & cli_adresse, & cli_address_len ) ) == - 1 ) {
feil ( 'Kunne ikke godta' ) ;
exit ( EXIT_FAILURE ) ;
}

lese ( cli_socket, buf, MAX_BUF_SIZE ) ;
cout << 'Kundens melding er: ' << buff << endl ;

sende ( cli_socket, 'Servers melding' , strlen ( 'Servers melding' ) , 0 ) ;

Lukk ( cli_socket ) ;
Lukk ( ser_socket ) ;

komme tilbake 0 ;
}

Det gitte eksemplet er server-side-koden til C++-programmet. Denne koden fungerer for en enkel TCP-server for å lytte etter tilkoblinger på en enkelt spesifikk port. Når en tilkobling er opprettet, vil serveren motta en melding som sendes fra klienten. Etter det skriver den det ut på konsollen og sender en svarmelding til klienten. La oss forstå hver linje med kode.



Programmet starter med å inkludere bibliotekene: 'iostream' for standard input/output definisjoner, 'cstring' for strenghåndteringsfunksjoner, 'unistd.h' for å gi tilgang til POSIX operativsystem API, og 'arpa/inet.h' for å utføre internettoperasjoner. '#define PORT 8080'-setningen betyr at den definerer portnummeret 8080 som serveren vil lytte til. '#define MAX_BUF_SIZE 1024' betyr den maksimale bufferstørrelsen for innkommende data som er 1024.





I hovedfunksjonen initialiseres to variabler, 'ser_socket' og 'cli_socket', for å representere henholdsvis serveren og klienten. De tre andre variablene som er 'sockaddr_in', 'ser_address' og 'cli_address' av typen 'struct' initialiseres som adressestrukturer for serveren og klienten. Etter det initialiseres en buffer kalt 'buf' som lagrer dataene som kommer fra klienten.

Socket()-funksjonen i 'if'-tilstanden oppretter en ny TCP-socket. AF_INET angir IPv4, SOCK_STREAM representerer den tilkoblingsorienterte og pålitelige TCP-kontakten, det siste argumentet som er 0 gis for å velge standard TCP-protokoll, INADDR_ANY godtar tilkoblingene på en hvilken som helst IP-adresse, og htons (PORT) konverterer portnummeret fra vertsbyte-rekkefølge til nettverksbyte-rekkefølgen.



Siden alt er riktig definert, er neste trinn å sette opp serveren som en lister på den gitte porten og godta tilkoblingene på et hvilket som helst nettverksgrensesnitt. Socket er gitt med informasjonen i 'ser_address' av bind()-metoden. Vi skriver ut en feil og avslutter prosessen dersom bindingen mislykkes. Accept()-funksjonen åpner en ny socket for tilkoblingen med klienten, mens listen()-funksjonen instruerer serveren til å vente på innkommende tilkoblinger. Hvis aksept()-funksjonen mislykkes, skrives feilmeldingen ut og funksjonen avsluttes.

Deretter leser serveren klientmeldingen med read()-funksjonen inn i 'buf'-bufferen og skriver den deretter ut til konsollen. Send()-funksjonen brukes av serveren til å sende en melding som svar til klienten. Til slutt, ved å bruke close(), lukker serveren klientens socket, og avslutter programmet slik at alle tilkoblinger lukkes ordentlig og det er ingen sannsynlighet for datainnbrudd.

2. Klientside

La oss nå se hva som skjer i klientmodellen:

#include
#include
#include
#include

#define PORT 8080
#define SERVER_IP '127.0.0.1'

int hoved- ( ) {
int cli_socket ;
struktur sockaddr_in ser_address ;
konst røye * beskjed = 'Klienten sender hilsener!' ;

hvis ( ( cli_socket = stikkontakt ( AF_INET, SOCK_STREAM, 0 ) ) == - 1 ) {
feil ( 'Feil ved oppretting av sokkel' ) ;
exit ( EXIT_FAILURE ) ;
}

ser_adresse. sin_familie = OF_INET ;
ser_adresse. sin_port = htons ( HAVN ) ;

hvis ( inet_pton ( AF_INET, SERVER_IP, & ser_adresse. sin_addr ) <= 0 ) {
feil ( 'Feil adresse' ) ;
exit ( EXIT_FAILURE ) ;
}

hvis ( koble ( cli_socket, ( struktur sockaddr * ) & ser_adresse, størrelsen av ( ser_adresse ) ) == - 1 ) {
feil ( 'Tilkoblingsfeil' ) ;
exit ( EXIT_FAILURE ) ;
}
sende ( cli_socket, melding, strlen ( beskjed ) , 0 ) ;

røye buff [ 1024 ] = { 0 } ;
lese ( cli_socket, buf, størrelsen av ( buff ) ) ;
std :: cout << 'Serversvar: ' << buff << std :: endl ;

Lukk ( cli_socket ) ;
komme tilbake 0 ;
}

La oss se hver linje med kode for å forstå hvordan programmet fungerer.

De samme fire bibliotekene – iostream, cstring, unistd.h og arpa/inet.h – er også inkludert på klientsiden. Et portnummer er også definert sammen med IP-adressen til den lokale verten 127.0.0.1. Meldingen som skal leveres til serveren er gitt. Klienten og serveren må opprette en tilkobling som følgende trinn:

'if ((client_socket = socket(AF_INET, SOCK_STREAM, 0)) == -1);' oppretter en socket for IPv4 med en strømtype og standardprotokollen TCP. Perror() skriver ut feildetaljene hvis socket()-funksjonen ikke klarer å etablere en tilkobling og avslutter programmet.

«server_address.sin_port = htons(PORT);» setter portnummeret etter konvertering til nettverksbyte-rekkefølgen. Etterpå blir det gitt en annen feilmelding som er 'Feil adresse' som skrives ut hvis det er noe galt med adressen. Ved å finne adressen i 'ser_address', vil klienten koble seg til serveren. Hvis tilkoblingen mislykkes, skrives feildetaljene ut. Send()-funksjonen vil overføre meldingen til serveren, og sikre at den ikke inneholder noe flagg.

For å motta og lagre et svar fra serveren, initialiseres en buffer kalt 'buf' av typen 'char'. Read()-funksjonen leser serverens svar inn i bufferen. Til slutt skrives serverens svar ut til konsollen. Til slutt lukkes forbindelsen ved å bruke close()-setningen for å avslutte socket. Følgende er resultatet av programmet:

Konklusjon

Socket-programmering er en viktig del av nettverkskommunikasjon innen informatikk. Det muliggjør utvikling av applikasjoner som kan kommunisere over nettverket, og muliggjør et bredt spekter av muligheter fra enkle klient-server-arkitekturer til strukturerte distribuerte systemer. Når en socket opprettes i en programmeringskontekst, må programmet konfigurere endepunktkarakteristikkene som protokollene, TCP eller UDP, og nettverksadressen som IP-adressen og portnummeret. Disse kontaktene lar serverne sende og motta dataene. Denne artikkelen viser et praktisk eksempel på hvordan klient-server-modellen i socket-programmering fungerer.