Socket programozás C++ nyelven

Socket Programozas C Nyelven



A socket programozás a számítógépes hálózatok területén fontos témává vált. Ez magában foglalja a kapcsolat létrehozását két csomópont, a szerver és az ügyfél között, hogy megszakítás nélkül kommunikáljanak egymással. A szerver figyelőként működik a kommunikációs csatornában, és egy adott porton egy IP-címen figyeli a klienst. Másrészt a kliens kommunikátorként működik a kommunikációs csatornában. Az ügyfél felveszi a kapcsolatot a szerverrel, hogy kapcsolatot hozzon létre, és kapcsolatot létesítsen a szerverrel. Ennek a cikknek az a célja, hogy átfogó és részletes útmutatót adjon a socket programozáshoz C++ nyelven, lefedi az alapokat, gyakorlati példákat mutat be, és részletes magyarázatot ad a kódról.

A kliens-szerver modell kialakítása

A socket programozás az a folyamat, amely socketek segítségével kommunikációs csatornát épít ki a szerver és a kliens között. A következő példakódban az ügyfél kapcsolatot létesít a kiszolgálóval, és a kiszolgáló be van állítva az ügyfélkapcsolatok fogadására. Ismerjük meg a szerver és kliens kódszegmenseit, bemutatva a hálózati kommunikáción belüli működésüket. A következő a szerveroldali kód. Nézzük először a kódot, majd magyarázzuk el részletesen, pontról pontra.

1. Szerver oldal







A modell szerveroldali kódja az alábbiakban található. Lássuk, mi történik a kódban:



#include
#include
#include
#include

segítségével névtér std ;

#define PORT 8080
#define MAX_BUF_SIZE 1024

int fő- ( ) {
int ser_socket, cli_socket ;
struct sockaddr_in szer_cím, kliens_cím ;
char buf [ MAX_BUF_SIZE ] = { 0 } ;

ha ( ( ser_socket = foglalat ( AF_INET, SOCK_STREAM, 0 ) ) == - 1 ) {
tévedés ( 'Hiba a socket létrehozásánál' ) ;
kijárat ( EXIT_FAILURE ) ;
}

szer_cím. bűn_család = OF_INET ;
szer_cím. sin_addr . s_addr = INADDR_ANY ;
szer_cím. sin_port = htons ( KIKÖTŐ ) ;

ha ( kötni ( be_socket, ( struct sockaddr * ) & szer_cím, mérete ( szer_cím ) ) == - 1 ) {
tévedés ( 'kötési hiba' ) ;
kijárat ( EXIT_FAILURE ) ;
}

ha ( hallgat ( be_socket, 3 ) == - 1 ) {
tévedés ( 'Nem sikerült meghallgatni' ) ;
kijárat ( EXIT_FAILURE ) ;
}

cout << 'Szerver figyel a porton' << KIKÖTŐ << '... \n ' ;

socklen_t cli_address_len = mérete ( kliens_cím ) ;
ha ( ( cli_socket = elfogad ( be_socket, ( struct sockaddr * ) & cli_address, & cli_address_len ) ) == - 1 ) {
tévedés ( 'Nem sikerült elfogadni' ) ;
kijárat ( EXIT_FAILURE ) ;
}

olvas ( cli_socket, buf, MAX_BUF_SIZE ) ;
cout << 'Az ügyfél üzenete:' << buf << endl ;

Küld ( cli_socket, 'Szerver üzenete' , strlen ( 'Szerver üzenete' ) , 0 ) ;

Bezárás ( cli_socket ) ;
Bezárás ( ser_socket ) ;

Visszatérés 0 ;
}

A megadott példa a C++ program szerveroldali kódja. Ez a kód egy egyszerű TCP-kiszolgálón működik, amely egyetlen porton figyeli a kapcsolatokat. Amikor a kapcsolat sikeresen létrejött, a szerver üzenetet kap az ügyféltől. Ezt követően kinyomtatja a konzolra, és válaszüzenetet küld a kliensnek. Értsük meg a kód minden sorát.



A program a következő könyvtárak beépítésével kezdődik: „iostream” a szabványos bemeneti/kimeneti definíciókhoz, „cstring” a karakterlánc-kezelő funkciókhoz, „unistd.h” a POSIX operációs rendszer API-jához való hozzáférés biztosításához, és „arpa/inet.h” végezze el az internetes műveleteket. A „#define PORT 8080” utasítás azt jelenti, hogy meghatározza a 8080-as portszámot, amelyen a szerver figyelni fog. A „#define MAX_BUF_SIZE 1024” a bejövő adatok maximális pufferméretét jelenti, amely 1024.





A fő függvényben két változó van inicializálva, a „ser_socket” és a „cli_socket”, amelyek mind a szervert, mind a klienst képviselik. A másik három változó, a „sockaddr_in”, „ser_address” és „cli_address” „struct” típusú, címstruktúraként inicializálva van a szerver és az ügyfél számára. Ezt követően egy „buf” nevű puffer inicializálódik, amely az ügyféltől származó adatokat tárolja.

A socket() függvény az „if” feltételben új TCP socketet hoz létre. Az AF_INET az IPv4, a SOCK_STREAM a kapcsolatorientált és megbízható TCP socket, az utolsó argumentum, amely 0, az alapértelmezett TCP protokoll kiválasztásához, az INADDR_ANY bármilyen IP-címen fogadja a kapcsolatokat, a htons (PORT) pedig a portszámot konvertálja a host byte order a hálózati bájtsorrendhez.



Mivel minden megfelelően van definiálva, a következő lépés az, hogy a szervert listerként kell beállítani az adott porton, és bármilyen hálózati interfészen elfogadni a kapcsolatokat. A socketet a „ser_address”-ben lévő információkkal együtt a bind() metódus adja. Hibát nyomtatunk, és leállítjuk a folyamatot, ha a kötés sikertelen. Az accept() függvény új socketet nyit meg az ügyféllel való kapcsolathoz, míg a listen() függvény arra utasítja a szervert, hogy várja meg a bejövő kapcsolatokat. Ha az accept() függvény sikertelen, a hibaüzenet kinyomtatásra kerül, és a függvény kilép.

Ezután a szerver beolvassa az ügyfélüzenetet a read() függvénnyel a „buf” pufferbe, majd kinyomtatja a konzolra. A send() függvényt a szerver arra használja, hogy üzenetet küldjön válaszul a kliensnek. Végül a close() segítségével a szerver bezárja a kliens socketjét, leállítva a programot, így minden kapcsolat megfelelően bezárul, és nem áll fenn az adatszivárgás valószínűsége.

2. Ügyféloldal

Most pedig lássuk, mi történik az ügyfélmodellben:

#include
#include
#include
#include

#define PORT 8080
#define SERVER_IP '127.0.0.1'

int fő- ( ) {
int cli_socket ;
struct sockaddr_in szer_address ;
const char * üzenet = 'Üdvözletet küld az ügyfél!' ;

ha ( ( cli_socket = foglalat ( AF_INET, SOCK_STREAM, 0 ) ) == - 1 ) {
tévedés ( 'Hiba a socket létrehozásakor' ) ;
kijárat ( EXIT_FAILURE ) ;
}

szer_cím. bűn_család = OF_INET ;
szer_cím. sin_port = htons ( KIKÖTŐ ) ;

ha ( inet_pton ( AF_INET, SERVER_IP, & szer_cím. sin_addr ) <= 0 ) {
tévedés ( 'Rossz cím' ) ;
kijárat ( EXIT_FAILURE ) ;
}

ha ( csatlakozni ( cli_socket, ( struct sockaddr * ) & szer_cím, mérete ( szer_cím ) ) == - 1 ) {
tévedés ( 'Kapcsolathiba' ) ;
kijárat ( EXIT_FAILURE ) ;
}
Küld ( cli_socket, mesg, strlen ( üzenet ) , 0 ) ;

char buf [ 1024 ] = { 0 } ;
olvas ( cli_socket, buf, mérete ( buf ) ) ;
std :: cout << 'Szerver válasza:' << buf << std :: endl ;

Bezárás ( cli_socket ) ;
Visszatérés 0 ;
}

Nézzük meg az egyes kódsorokat, hogy megértsük a program működését.

Ugyanez a négy könyvtár – iostream, cstring, unistd.h és arpa/inet.h – szintén szerepel az ügyféloldalon. A 127.0.0.1 helyi gazdagép IP-címével együtt egy portszám is meghatározásra kerül. Megjelenik az üzenet, amelyet el kell juttatni a szerverhez. A kliensnek és a szervernek kapcsolatot kell létesítenie a következő lépések szerint:

Az 'if ((kliens_socket = socket(AF_INET, SOCK_STREAM, 0)) == -1);' létrehoz egy socketet az IPv4 számára egy adatfolyamtípussal és az alapértelmezett TCP protokollal. A perror() kiírja a hiba részleteit, ha a socket() függvény nem tud kapcsolatot létesíteni, és kilép a programból.

A 'szerver_címe.sin_port = htons(PORT);' beállítja a portszámot a hálózati bájtsorrendre való átalakítás után. Ezt követően egy másik hibaüzenet jelenik meg, ez a „Rossz cím”, amelyet kinyomtat, ha valami nem stimmel a címmel. A cím megtalálásával a „szer_címben” a kliens csatlakozni fog a szerverhez. Ha a kapcsolat sikertelen, a hiba részletei kinyomtatásra kerülnek. A send() függvény továbbítja az üzenetet a szervernek, biztosítva, hogy az ne tartalmazzon jelzőt.

A kiszolgálótól érkező válasz fogadásához és tárolásához a „char” típusú „buf” nevű puffert inicializálják. A read() függvény beolvassa a szerver válaszát a pufferbe. Végül a szerver válasza kinyomtatásra kerül a konzolra. Végül a kapcsolatot lezárjuk a close() utasítással a socket leállításához. A program kimenete a következő:

Következtetés

A socket programozás a számítástechnikában a hálózati kommunikáció fontos része. Lehetővé teszi olyan alkalmazások fejlesztését, amelyek képesek a hálózaton keresztül kommunikálni, és az egyszerű kliens-szerver architektúráktól a strukturált elosztott rendszerekig a lehetőségek széles skáláját teszi lehetővé. Amikor egy socket programozási környezetben jön létre, a programnak konfigurálnia kell a végpont jellemzőit, például a protokollokat, a TCP-t vagy az UDP-t, valamint a hálózati címet, például az IP-címet és a portszámot. Ezek a socketek lehetővé teszik a szerverek számára az adatok küldését és fogadását. Ez a cikk gyakorlati példát mutat be a kliens-szerver modell működésére a socket programozásban.