Socketprogrammering i C++

Socketprogrammering I C



Socket-programmering har blivit ett viktigt ämne inom området datornätverk. Det innebär att upprätta en anslutning mellan två noder, server och klient för att kommunicera med varandra utan avbrott. Servern fungerar som en lyssnare i kommunikationskanalen och lyssnar på klienten på en specifik port på en IP-adress. Å andra sidan fungerar klienten som kommunikatör i kommunikationskanalen. Klienten kontaktar servern för att skapa en anslutning och skapa en kontakt med servern. Den här artikeln syftar till att ge en omfattande och detaljerad guide till socketprogrammering i C++, som täcker grunderna, presenterar praktiska exempel och ger en detaljerad förklaring av koden.

Etablering av klient-servermodellen

Socketprogrammering är den process som bygger en kommunikationskanal mellan servern och klienten med hjälp av sockets. I följande exempelkod startar klienten en kontakt med servern och servern är inställd för att acceptera klientanslutningarna. Låt oss förstå server- och klientkodsegmenten genom att demonstrera deras kärnverksamhet inom nätverkskommunikationen. Följande är serversidans kod. Låt oss först se koden och sedan förklara koden i detalj, punkt för punkt.

1. Serversidan







Koden för modellens serversida ges i det följande. Låt oss se vad som händer i koden:



#include
#include
#include
#include

använder sig av namnutrymme std ;

#define PORT 8080
#define MAX_BUF_SIZE 1024

int huvud ( ) {
int ser_socket, cli_socket ;
struktur sockaddr_in ser_address, cli_address ;
röding buff [ MAX_BUF_SIZE ] = { 0 } ;

om ( ( ser_socket = uttag ( AF_INET, SOCK_STREAM, 0 ) ) == - 1 ) {
fel ( 'Fel vid skapandet av Socket' ) ;
utgång ( EXIT_FAILURE ) ;
}

ser_adress. synd_familj = OF_INET ;
ser_adress. sin_addr . s_addr = INADDR_ANY ;
ser_adress. sin_port = htons ( HAMN ) ;

om ( binda ( be_socket, ( struktur sockaddr * ) & ser_adress, storlek av ( ser_adress ) ) == - 1 ) {
fel ( 'Feil i bindning' ) ;
utgång ( EXIT_FAILURE ) ;
}

om ( lyssna ( be_socket, 3 ) == - 1 ) {
fel ( 'Det gick inte att lyssna' ) ;
utgång ( EXIT_FAILURE ) ;
}

cout << 'Server lyssnar på port' << HAMN << '... \n ' ;

socklen_t cli_address_len = storlek av ( cli_adress ) ;
om ( ( cli_socket = acceptera ( be_socket, ( struktur sockaddr * ) & cli_adress, & cli_address_len ) ) == - 1 ) {
fel ( 'Det gick inte att acceptera' ) ;
utgång ( EXIT_FAILURE ) ;
}

läsa ( cli_socket, buf, MAX_BUF_SIZE ) ;
cout << 'Kundens meddelande är:' << buff << endl ;

skicka ( cli_socket, 'Servers meddelande' , strlen ( 'Servers meddelande' ) , 0 ) ;

stänga ( cli_socket ) ;
stänga ( ser_socket ) ;

lämna tillbaka 0 ;
}

Det givna exemplet är serversidans kod för C++-programmet. Denna kod fungerar för en enkel TCP-server för att lyssna efter anslutningar på en enda specifik port. När en anslutning har skapats kommer servern att ta emot ett meddelande som skickas från klienten. Efter det skriver den ut den på konsolen och skickar ett svarsmeddelande till klienten. Låt oss förstå varje kodrad.



Programmet börjar med att inkludera biblioteken: 'iostream' för standardin-/utgångsdefinitioner, 'cstring' för stränghanteringsfunktioner, 'unistd.h' för att ge tillgång till POSIX operativsystems API och 'arpa/inet.h' för att utföra internetoperationer. '#define PORT 8080'-satsen betyder att den definierar portnumret 8080 som servern kommer att lyssna på. '#define MAX_BUF_SIZE 1024' betyder den maximala buffertstorleken för inkommande data som är 1024.





I huvudfunktionen initieras två variabler, 'ser_socket' och 'cli_socket', för att representera både servern respektive klienten. De andra tre variablerna som är 'sockaddr_in', 'ser_address' och 'cli_address' av typen 'struct' initieras som adressstrukturer för servern och klienten. Därefter initieras en buffert som heter 'buf' som lagrar data som kommer från klienten.

Funktionen socket() i 'if'-tillståndet skapar en ny TCP-socket. AF_INET betecknar IPv4, SOCK_STREAM representerar den anslutningsorienterade och pålitliga TCP-socket, det sista argumentet som är 0 ges för att välja standard TCP-protokoll, INADDR_ANY accepterar anslutningarna på vilken IP-adress som helst och htons (PORT) konverterar portnumret från värdbyteordning till nätverksbyteordning.



Eftersom allt är korrekt definierat är nästa steg att ställa in servern som en lister på den givna porten och acceptera anslutningarna på alla nätverksgränssnitt. Socket ges med informationen i 'ser_address' med bind()-metoden. Vi skriver ut ett fel och avslutar processen om bindningen misslyckas. Accept()-funktionen öppnar en ny socket för anslutningen med klienten, medan listen()-funktionen instruerar servern att vänta på inkommande anslutningar. Om funktionen accept() misslyckas skrivs felmeddelandet ut och funktionen avslutas.

Därefter läser servern klientmeddelandet med read()-funktionen in i 'buff'-bufferten och skriver sedan ut det till konsolen. Send()-funktionen används av servern för att skicka ett meddelande som svar till klienten. Slutligen, med hjälp av close(), stänger servern klientens socket och avslutar programmet så att alla anslutningar stängs ordentligt och det inte finns någon sannolikhet för dataintrång.

2. Kundsidan

Låt oss nu se vad som händer i klientmodellen:

#include
#include
#include
#include

#define PORT 8080
#define SERVER_IP '127.0.0.1'

int huvud ( ) {
int cli_socket ;
struktur sockaddr_in ser_address ;
konst röding * meddelande = 'Kunden skickar hälsningar!' ;

om ( ( cli_socket = uttag ( AF_INET, SOCK_STREAM, 0 ) ) == - 1 ) {
fel ( 'Fel vid skapandet av socket' ) ;
utgång ( EXIT_FAILURE ) ;
}

ser_adress. synd_familj = OF_INET ;
ser_adress. sin_port = htons ( HAMN ) ;

om ( inet_pton ( AF_INET, SERVER_IP, & ser_adress. sin_addr ) <= 0 ) {
fel ( 'Fel adress' ) ;
utgång ( EXIT_FAILURE ) ;
}

om ( ansluta ( cli_socket, ( struktur sockaddr * ) & ser_adress, storlek av ( ser_adress ) ) == - 1 ) {
fel ( 'Anslutningsfel' ) ;
utgång ( EXIT_FAILURE ) ;
}
skicka ( cli_socket, mesg, strlen ( meddelande ) , 0 ) ;

röding buff [ 1024 ] = { 0 } ;
läsa ( cli_socket, buf, storlek av ( buff ) ) ;
std :: cout << 'Serversvar:' << buff << std :: endl ;

stänga ( cli_socket ) ;
lämna tillbaka 0 ;
}

Låt oss se varje rad med kod för att förstå hur programmet fungerar.

Samma fyra bibliotek – iostream, cstring, unistd.h och arpa/inet.h – finns också på klientsidan. Ett portnummer definieras också tillsammans med IP-adressen för den lokala värden 127.0.0.1. Meddelandet som måste levereras till servern ges. Klienten och servern måste upprätta en anslutning enligt följande steg:

'if ((client_socket = socket(AF_INET, SOCK_STREAM, 0)) == -1);' skapar en socket för IPv4 med en strömtyp och standardprotokollet TCP. Perror() skriver ut felinformationen om socket()-funktionen misslyckas med att upprätta en anslutning och avslutar programmet.

'server_address.sin_port = htons(PORT);' ställer in portnumret efter konvertering till nätverkets byteordning. Efteråt ges ett annat felmeddelande som är 'Fel adress' som skrivs ut om det är något fel på adressen. Genom att lokalisera adressen i 'ser_address' kommer klienten att ansluta till servern. Om anslutningen misslyckas skrivs felinformationen ut. Send()-funktionen överför meddelandet till servern och säkerställer att det inte innehåller någon flagga.

För att ta emot och lagra ett svar från servern initieras en buffert med namnet 'buf' av typen 'char'. Read()-funktionen läser in serverns svar i bufferten. Slutligen skrivs serverns svar ut till konsolen. Slutligen stängs anslutningen med hjälp av close()-satsen för att avsluta socket. Följande är resultatet av programmet:

Slutsats

Socket-programmering är en viktig del av nätverkskommunikation inom datavetenskap. Det möjliggör utveckling av applikationer som kan kommunicera över nätverket, vilket möjliggör ett brett utbud av möjligheter från enkla klient-server-arkitekturer till strukturerade distribuerade system. När en socket skapas i ett programmeringssammanhang måste programmet konfigurera dess ändpunktsegenskaper såsom protokoll, TCP eller UDP, och nätverksadressen som IP-adress och portnummer. Dessa uttag låter servrarna skicka och ta emot data. Den här artikeln visar ett praktiskt exempel på hur klient-servermodellen i socketprogrammering fungerar.