Programiranje utičnica je način povezivanja dvaju čvorova na mreži radi međusobnog komuniciranja. Jedna utičnica (čvor) sluša određeni port na IP-u dok druga utičnica dopire do druge kako bi uspostavila vezu. Poslužitelj formira utičnicu slušatelja dok klijent dopire do poslužitelja.
Programiranje utičnica naširoko se koristi u aplikacijama za razmjenu trenutnih poruka, binarnom strujanju i suradnji na dokumentima, platformama za online strujanje itd.
Primjer
U ovom C programu razmjenjujemo jednu pozdravnu poruku između poslužitelja i klijenta kako bismo demonstrirali model klijent/poslužitelj.
poslužitelj.c
C#include #include #include #include #include #include #define PORT 8080 int main(int argc char const* argv[]) { int server_fd new_socket; ssize_t valread; struct sockaddr_in address; int opt = 1; socklen_t addrlen = sizeof(address); char buffer[1024] = { 0 }; char* hello = 'Hello from server'; // Creating socket file descriptor if ((server_fd = socket(AF_INET SOCK_STREAM 0)) < 0) { perror('socket failed'); exit(EXIT_FAILURE); } // Forcefully attaching socket to the port 8080 if (setsockopt(server_fd SOL_SOCKET SO_REUSEADDR | SO_REUSEPORT &opt sizeof(opt))) { perror('setsockopt'); exit(EXIT_FAILURE); } address.sin_family = AF_INET; address.sin_addr.s_addr = INADDR_ANY; address.sin_port = htons(PORT); // Forcefully attaching socket to the port 8080 if (bind(server_fd (struct sockaddr*)&address sizeof(address)) < 0) { perror('bind failed'); exit(EXIT_FAILURE); } if (listen(server_fd 3) < 0) { perror('listen'); exit(EXIT_FAILURE); } if ((new_socket = accept(server_fd (struct sockaddr*)&address &addrlen)) < 0) { perror('accept'); exit(EXIT_FAILURE); } // subtract 1 for the null // terminator at the end valread = read(new_socket buffer 1024 - 1); printf('%sn' buffer); send(new_socket hello strlen(hello) 0); printf('Hello message sentn'); // closing the connected socket close(new_socket); // closing the listening socket close(server_fd); return 0; }
klijent.c
C#include #include #include #include #include #define PORT 8080 int main(int argc char const* argv[]) { int status valread client_fd; struct sockaddr_in serv_addr; char* hello = 'Hello from client'; char buffer[1024] = { 0 }; if ((client_fd = socket(AF_INET SOCK_STREAM 0)) < 0) { printf('n Socket creation error n'); return -1; } serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(PORT); // Convert IPv4 and IPv6 addresses from text to binary // form if (inet_pton(AF_INET '127.0.0.1' &serv_addr.sin_addr) <= 0) { printf( 'nInvalid address/ Address not supported n'); return -1; } if ((status = connect(client_fd (struct sockaddr*)&serv_addr sizeof(serv_addr))) < 0) { printf('nConnection Failed n'); return -1; } // subtract 1 for the null // terminator at the end send(client_fd hello strlen(hello) 0); printf('Hello message sentn'); valread = read(client_fd buffer 1024 - 1); printf('%sn' buffer); // closing the connected socket close(client_fd); return 0; }
Sastavljanje
gcc client.c -o clientgcc server.c -o server
Izlaz
Client:Hello message sentHello from serverServer:Hello from clientHello message sentKomponente programiranja utičnica
1. Utičnice
Utičnice su jedna od ključnih komponenti koje koristi program za pristup mreži za komunikaciju s drugim procesima/čvorovima preko mreže. To je jednostavno kombinacija IP adrese i broja porta koji djeluje kao krajnja točka za komunikaciju.
Primjer: 192.168.1.1:8080 gdje dva dijela odvojena dvotočkom predstavljaju IP adresa (192.168.1.1) i broj priključka (8080).
Vrste utičnica:
- TCP utičnica (Stream Socket): Pruža pouzdanu komunikaciju temeljenu na vezi (tj. TCP protokol ).
- UDP utičnica (datagramska utičnica): Omogućuje komunikaciju bez veze bržu, ali nepouzdanu (tj. UDP protokol ).
2. Model klijent-poslužitelj
The model klijent-poslužitelj odnosi se na arhitekturu koja se koristi u programiranju utičnica gdje klijent i poslužitelj međusobno komuniciraju radi razmjene informacija ili usluga. Ova arhitektura omogućuje klijentu slanje zahtjeva za uslugama, a poslužitelju obradu i slanje odgovora na te zahtjeve za uslugama.
Dijagram stanja za model poslužitelja i klijenta
Dijagram stanja za poslužiteljski i klijentski model utičniceProgramiranje utičnica u C-u moćan je način upravljanja mrežnom komunikacijom.
Stvaranje procesa na strani poslužitelja
Poslužitelj se kreira pomoću sljedećih koraka:
rezanje polja java
1. Stvaranje utičnice
Ovaj korak uključuje stvaranje utičnice pomoću funkcije socket().
Parametri:
- sockfd: deskriptor utičnice cijeli broj (kao ručka datoteke)
- domena: cijeli broj specificira komunikacijsku domenu. Koristimo AF_ LOCAL kako je definirano u POSIX standardu za komunikaciju između procesa na istom hostu. Za komunikaciju između procesa na različitim hostovima povezanim putem IPV4 koristimo AF_INET i AF_I NET 6 za procese povezane putem IPV6.
- tip: vrsta komunikacije
SOCK_STREAM: TCP (orijentiran na pouzdanu vezu)
SOCK_DGRAM: UDP (nepouzdana veza bez veze) - protokol: Vrijednost protokola za internetski protokol (IP) koja je 0. To je isti broj koji se pojavljuje u polju protokola u IP zaglavlju paketa. (man protokoli za više detalja)
sockfd = socket(domain type protocol)
2. Postavite opciju utičnice
Ovo pomaže u manipuliranju opcijama za utičnicu koju upućuje deskriptor datoteke sockfd. Ovo je potpuno izborno, ali pomaže u ponovnoj upotrebi adrese i priključka. Sprječava pogreške kao što su: adresa se već koristi.
Csetsockopt(sockfd level optname optval socklen_t optlen);
3. Svežite
Nakon stvaranja utičnice funkcija bind() povezuje utičnicu s adresom i brojem priključka navedenim u addr(prilagođena struktura podataka). U primjeru koda povezujemo poslužitelj s lokalnim hostom stoga koristimo INADDR_ANY za određivanje IP adrese.
C++bind(sockfd sockaddr *addr socklen_t addrlen);
Parametri:
- sockfd : deskriptor datoteke utičnice kreiran pomoću funkcije socket().
- adresa : pokazivač na strukturu sockaddr koja sadrži IP adresu i broj porta za povezivanje utičnice.
- addrlen : duljina strukture addr.
4. Slušajte
U ovom koraku poslužitelj koristi funkciju listen() koja stavlja poslužiteljsku utičnicu u pasivni način rada gdje čeka da klijent priđe poslužitelju kako bi uspostavio vezu. Zaostatak definira maksimalnu duljinu do koje može narasti red veza na čekanju za sockfd. Ako zahtjev za povezivanjem stigne kada je red čekanja pun, klijent može primiti pogrešku s indikacijom ECONNREFUSED.
Clisten(sockfd backlog);
Parametri :
- sockfd : deskriptor datoteke utičnice kreiran pomoću funkcije socket().
- zaostatak : broj koji predstavlja veličinu reda koji drži veze na čekanju dok poslužitelj čeka da prihvati vezu.
5. Prihvatite
U ovom koraku poslužitelj izdvaja prvi zahtjev za povezivanjem iz reda čekanja veza za utičnicu koja sluša sockfd stvara novu povezanu utičnicu koristeći prihvatiti() funkciju i vraća novi deskriptor datoteke koji se odnosi na tu utičnicu. U ovom trenutku uspostavljena je veza između klijenta i poslužitelja i oni su spremni za prijenos podataka.
Cnew_socket= accept(sockfd sockaddr *addr socklen_t *addrlen);
Parametri:
- sockfd : deskriptor datoteke utičnice vraćen pomoću socket() i bind().
- adresa : pokazivač na strukturu sockaddr koja će sadržavati klijentovu IP adresu i broj porta.
- addrlen : pokazivač na varijablu koja specificira duljinu strukture adrese.
6. Pošalji/Primi
U ovom koraku poslužitelj može slati ili primati podatke od klijenta.
Poslati(): za slanje podataka klijentu
Csend(sockfd *buf len flags);
Parametri:
- sockfd : deskriptor datoteke utičnice koji vraća funkcija socket().
- buf : pokazivač na međuspremnik koji sadrži podatke koji se šalju.
- samo : broj bajtova podataka za slanje.
- zastave : cijeli broj koji navodi različite opcije za način na koji se podaci obično šalju. 0 se koristi za zadano ponašanje.
Primi() : za primanje podataka od klijenta.
Crecv( sockfd *buf len flags);
Parametri:
- sockfd : deskriptor datoteke utičnice koji vraća funkcija socket().
- buf : pokazivač na međuspremnik koji sadrži podatke koje treba pohraniti.
- samo : broj bajtova podataka za slanje.
- zastave : cijeli broj koji navodi različite opcije za način na koji se podaci obično šalju. 0 se koristi za zadano ponašanje.
6. Zatvorite
Nakon završetka razmjene informacija poslužitelj zatvara utičnicu pomoću funkcije close() i oslobađa resurse sustava.
Cclose(fd);
Parametri:
- fd: deskriptor datoteke utičnice.
Stvaranje procesa na strani klijenta
Slijedite korake u nastavku za stvaranje procesa na strani klijenta:
1. Spajanje utičnice
Ovaj korak uključuje stvaranje utičnice koja se radi na isti način kao i kreiranje utičnice na poslužitelju
2. Povežite se
Sistemski poziv connect() povezuje utičnicu na koju upućuje deskriptor datoteke sockfd s adresom navedenom u addr. Adresa i port poslužitelja navedeni su u addr.
C++connect(sockfd sockaddr *addr socklen_t addrlen);
Parametri
- sockfd : deskriptor datoteke utičnice koji vraća funkcija socket().
- adresa : pokazivač na strukturu sockaddr koja sadrži IP adresu poslužitelja i broj porta.
- addrlen : veličina adrese
3. Pošalji/Primi
U ovom koraku klijent može slati ili primati podatke od poslužitelja što se radi pomoću funkcija send() i recieve() slično načinu na koji poslužitelj šalje/prima podatke od klijenta.
4. Zatvorite
Nakon što je razmjena informacija dovršena, klijent također treba zatvoriti stvorenu utičnicu i osloboditi sistemske resurse pomoću funkcije close() na isti način kao što to čini poslužitelj.
Uobičajeni problemi i njihovi popravci u programiranju utičnica
- Greške u vezi: Kako bismo izbjegli kvarove veze, trebali bismo osigurati da se klijent pokušava spojiti na ispravan IP adresa i port .
- Pogreške povezivanja priključka: Ove se pogreške pojavljuju kada se priključak već koristi od strane druge aplikacije u ovom scenariju vezanje na taj priključak neće uspjeti. Pokušajte upotrijebiti drugi priključak ili zatvorite prethodnu aplikaciju pomoću priključka.
- Blokiranje utičnica: Prema zadanim postavkama utičnice blokiraju. To znači da će pozivi poput accept() ili recv() čekati beskonačno dugo ako nema klijentske veze ili podataka. Ako je potrebno, utičnicu možete postaviti u način rada bez blokiranja.