Sokkelprogrammering i C

Sokkelprogrammering i C

Socket programmering er en måde at forbinde to noder på et netværk for at kommunikere med hinanden. Den ene socket(node) lytter på en bestemt port på en IP, mens den anden socket når ud til den anden for at danne en forbindelse. Serveren danner lytter-socket, mens klienten når ud til serveren.
Socket-programmering er meget udbredt i instant messaging-applikationer binær streaming og dokumentsamarbejde online streaming platforme osv.

Eksempel

I dette C-program udveksler vi en hej-besked mellem server og klient for at demonstrere klient/server-modellen.

server.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  (  '%s  n  '       buffer  );      send  (  new_socket       hello       strlen  (  hello  )     0  );      printf  (  'Hello message sent  n  '  );      // closing the connected socket      close  (  new_socket  );          // closing the listening socket      close  (  server_fd  );      return     0  ;   }   

klient.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  (      '  n  Invalid address/ Address not supported   n  '  );      return     -1  ;      }      if     ((  status      =     connect  (  client_fd       (  struct     sockaddr  *  )  &  serv_addr        sizeof  (  serv_addr  )))       <     0  )     {      printf  (  '  n  Connection Failed   n  '  );      return     -1  ;      }          // subtract 1 for the null      // terminator at the end      send  (  client_fd       hello       strlen  (  hello  )     0  );      printf  (  'Hello message sent  n  '  );      valread     =     read  (  client_fd       buffer        1024     -     1  );         printf  (  '%s  n  '       buffer  );      // closing the connected socket      close  (  client_fd  );      return     0  ;   }   


Kompilering

 gcc client.c -o clientgcc server.c -o server  


Produktion

 Client:Hello message sentHello from serverServer:Hello from clientHello message sent  

Komponenter i Socket-programmering

1. Stikkontakter

Stikkontakter er en af ​​kernekomponenterne, der bruges af programmet til at få adgang til netværket for at kommunikere med andre processer/knudepunkter over netværket. Det er simpelthen en kombination af en IP-adresse og et portnummer, der fungerer som et slutpunkt for kommunikation.
Eksempel: 192.168.1.1:8080 hvor de to dele adskilt af kolon repræsenterer IP-adresse (192.168.1.1) og den portnummer (8080).

Sokkeltyper:

  • TCP Socket (Stream Socket): Giver pålidelig forbindelsesbaseret kommunikation (dvs. TCP protokol ).
  • UDP Socket (Datagram Socket): Giver forbindelsesfri kommunikation hurtigere, men upålidelig (dvs. UDP protokol ).

2. Klient-servermodel

De klient-server model refererer til den arkitektur, der bruges i socket-programmering, hvor en klient og en server interagerer med hinanden for at udveksle information eller tjenester. Denne arkitektur giver klienten mulighed for at sende serviceanmodninger og serveren til at behandle og sende svar på disse serviceanmodninger.

Statusdiagram for server- og klientmodel

Sokkelprogrammering i CStatusdiagram for server- og klientmodel af Socket

Socket-programmering i C er en effektiv måde at håndtere netværkskommunikation på.

Oprettelse af en proces på serversiden

Serveren oprettes ved hjælp af følgende trin:

1. Socket Oprettelse

Dette trin involverer oprettelsen af ​​socket ved hjælp af socket()-funktionen.

Parametre:

  • sockfd: socket descriptor et heltal (som et filhåndtag)
  • domæne: heltal angiver kommunikationsdomæne. Vi bruger AF_ LOCAL som defineret i POSIX-standarden til kommunikation mellem processer på samme vært. Til kommunikation mellem processer på forskellige værter forbundet med IPV4 bruger vi AF_INET og AF_I NET 6 til processer forbundet med IPV6.
  • type: kommunikationstype
    SOCK_STREAM: TCP (pålidelig forbindelsesorienteret)
    SOCK_DGRAM: UDP (upålidelig forbindelsesløs)
  • protokol: Protokolværdi for Internet Protocol(IP), som er 0. Dette er det samme tal, som vises i protokolfeltet i IP-headeren på en pakke.(man-protokoller for flere detaljer)
C
   sockfd     =     socket  (  domain       type       protocol  )   

2. Indstil socket opt

Dette hjælper med at manipulere muligheder for socket, der henvises til af filbeskrivelsen sockfd. Dette er helt valgfrit, men det hjælper med genbrug af adresse og port. Forhindrer fejl som: adresse allerede i brug.

C
   setsockopt  (  sockfd       level       optname       optval       socklen_t     optlen  );   

3. Bind

Efter oprettelsen af ​​socket binder bind()-funktionen socket til den adresse og portnummer, der er angivet i addr(brugerdefineret datastruktur). I eksempelkoden binder vi serveren til den lokale vært, derfor bruger vi INADDR_ANY til at angive IP-adressen.

C++
   bind  (  sockfd       sockaddr     *  addr       socklen_t     addrlen  );   

Parametre:

  • sockfd : socket-filbeskrivelse oprettet ved hjælp af socket()-funktionen.
  • adr : peger på en struct sockaddr, der indeholder IP-adressen og portnummeret til at binde soklen.
  • addrlen : længden af ​​addr-strukturen.

4. Lyt

I dette trin bruger serveren listen()-funktionen, der sætter serversocket i en passiv tilstand, hvor den venter på, at klienten nærmer sig serveren for at oprette forbindelse. Efterslæbet definerer den maksimale længde, som køen af ​​afventende forbindelser til sockfd kan vokse til. Hvis en forbindelsesanmodning ankommer, når køen er fuld, kan klienten modtage en fejl med en indikation af ECONNREFUSED.

C
   listen  (  sockfd       backlog  );   

Parametre :

  • sockfd : socket-filbeskrivelse oprettet ved hjælp af socket()-funktionen.
  • efterslæb : tal, der repræsenterer størrelsen af ​​køen, der holder de afventende forbindelser, mens serveren venter på at acceptere en forbindelse.

5. Accepter

I dette trin udtrækker serveren den første forbindelsesanmodning fra køen af ​​afventende forbindelser til lyttesocket sockfd opretter en ny tilsluttet socket ved hjælp af acceptere() funktion og returnerer en ny filbeskrivelse, der henviser til den socket. På dette tidspunkt er forbindelsen etableret mellem klient og server, og de er klar til at overføre data.

C
   new_socket  =     accept  (  sockfd       sockaddr     *  addr       socklen_t     *  addrlen  );   

Parametre:

  • sockfd : socket-filbeskrivelse returneret af socket() og bind().
  • adr : peger på en struct sockaddr, der skal indeholde klientens IP-adresse og portnummer.
  • addrlen : pointer til en variabel, der angiver længden af ​​adressestrukturen.

6. Send/modtag

I dette trin kan serveren sende eller modtage data fra klienten.

Sende(): at sende data til klienten

C
   send  (  sockfd       *  buf       len       flags  );   

Parametre:

  • sockfd : socket-filbeskrivelse returneret af socket()-funktionen.
  • buf : peger på bufferen, der indeholder de data, der skal sendes.
  • kun : antal bytes data, der skal sendes.
  • flag : heltal, der angiver forskellige muligheder for, hvordan dataene sendes, bruges typisk 0 til standardadfærd.

Modtag(): at modtage data fra klienten.

C
   recv  (     sockfd       *  buf       len       flags  );   

Parametre:

  • sockfd : socket-filbeskrivelse returneret af socket()-funktionen.
  • buf : markør til bufferen, der indeholder de data, der skal lagres.
  • kun : antal bytes data, der skal sendes.
  • flag : heltal, der angiver forskellige muligheder for, hvordan dataene sendes, bruges typisk 0 til standardadfærd.

6. Luk

Efter at udvekslingen af ​​information er afsluttet, lukker serveren socket ved hjælp af close()-funktionen og frigiver systemressourcerne.

C
   close  (  fd  );   

Parametre:

  • fd: filbeskrivelse af socket.

Oprettelse af proces på klientsiden

Følg nedenstående trin for at oprette en proces på klientsiden:

1. Stikkontakt

Dette trin involverer oprettelsen af ​​socket, hvilket sker på samme måde som serverens socket-oprettelse

2. Tilslut

Connect()-systemkaldet forbinder den socket, der henvises til af filbeskrivelsen sockfd, til den adresse, der er angivet af addr. Serverens adresse og port er angivet i adr.

C++
   connect  (  sockfd       sockaddr     *  addr       socklen_t     addrlen  );   

Parametre

  • sockfd : socket-filbeskrivelse returneret af socket()-funktionen.
  • adr : pointer til struct sockaddr, der indeholder serverens IP-adresse og portnummer.
  • addrlen : størrelse på addr.

3. Send/modtag

I dette trin kan klienten sende eller modtage data fra serveren, hvilket gøres ved hjælp af funktionerne send() og recieve() svarende til hvordan serveren sender/modtager data fra klienten.

4. Luk

Når udvekslingen af ​​information er afsluttet, skal klienten også lukke den oprettede socket og frigive systemressourcerne ved hjælp af close()-funktionen på samme måde som serveren gør.

Almindelige problemer og deres rettelser i socket-programmering

  • Forbindelsesfejl: For at undgå forbindelsesfejl bør vi sikre, at klienten forsøger at oprette forbindelse til den rigtige IP-adresse og port .
  • Portbindingsfejl: Disse fejl opstår, når en port allerede er i brug af et andet program i dette scenarie, vil bindingen til den port mislykkes. Prøv at bruge en anden port, eller luk det forrige program ved hjælp af porten.
  • Blokering af stikkontakter: Som standard blokerer stikkontakter. Det betyder, at opkald som accept() eller recv() vil vente på ubestemt tid, hvis der ikke er nogen klientforbindelse eller data. Du kan indstille stikket til ikke-blokerende tilstand, hvis det er nødvendigt.
Opret quiz