Programovanie soketov v C
Čo je to Socket Programovanie?
Programovanie soketov je spôsob prepojenia dvoch uzlov v sieti, aby spolu komunikovali. Jeden soket (uzol) počúva na konkrétnom porte na IP, zatiaľ čo druhý soket siaha k druhému, aby vytvoril spojenie. Server vytvára soket načúvania, zatiaľ čo klient oslovuje server.
Stavový diagram pre model servera a klienta
Stavový diagram pre serverový a klientsky model Socketu
Etapy pre server
Server sa vytvorí pomocou nasledujúcich krokov:
1. Vytvorenie zásuvky
int sockfd = socket(domain, type, protocol)
- sockfd: deskriptor zásuvky, celé číslo (ako popisovač súboru) doména: celé číslo, špecifikuje komunikačnú doménu. Na komunikáciu medzi procesmi na rovnakom hostiteľovi používame AF_ LOCAL, ako je definované v štandarde POSIX. Na komunikáciu medzi procesmi na rôznych hostiteľoch pripojených cez IPV4 používame AF_INET a AF_I NET 6 pre procesy pripojené cez IPV6. typ: typ komunikácie
SOCK_STREAM: TCP (spoľahlivý, orientovaný na pripojenie)
SOCK_DGRAM: Protokol UDP (nespoľahlivý, bez pripojenia): Hodnota protokolu pre internetový protokol (IP), ktorá je 0. Toto je rovnaké číslo, aké sa zobrazuje v poli protokolu v hlavičke IP paketu. (ďalšie podrobnosti nájdete v protokoloch man)
2. Setsockopt
Pomáha to pri manipulácii s voľbami pre soket, na ktorý odkazuje deskriptor súboru sockfd. Toto je úplne voliteľné, ale pomáha pri opätovnom použití adresy a portu. Zabraňuje chybám, ako napríklad: adresa sa už používa.
int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);
3. Zviazať
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
Po vytvorení soketu funkcia bind naviaže soket na adresu a číslo portu špecifikované v addr (vlastná dátová štruktúra). Vo vzorovom kóde naviažeme server na localhost, preto na špecifikáciu IP adresy používame INADDR_ANY.
4. Počúvajte
int listen(int sockfd, int backlog);
Uvádza soket servera do pasívneho režimu, kde čaká, kým sa klient priblíži k serveru, aby vytvoril spojenie. Backlog definuje maximálnu dĺžku, do ktorej môže narásť front čakajúcich pripojení pre sockfd. Ak žiadosť o pripojenie príde, keď je front plný, klient môže dostať chybu s označením ECONNREFUSED.
5. Prijmite
int new_socket= accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
Extrahuje prvú požiadavku na pripojenie z frontu čakajúcich pripojení pre počúvajúci soket, sockfd, vytvorí nový pripojený soket a vráti nový deskriptor súboru odkazujúci na tento soket. V tomto bode sa vytvorí spojenie medzi klientom a serverom a sú pripravení na prenos údajov.
Etapy pre klienta
1. Zásuvkové pripojenie: Presne to isté ako pri vytváraní soketu servera
2. Pripojiť: Systémové volanie connect() spája soket, na ktorý odkazuje deskriptor súboru sockfd, na adresu zadanú addr. Adresa a port servera sú uvedené v adr.
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
Implementácia
Tu si vymieňame jednu pozdravnú správu medzi serverom a klientom, aby sme demonštrovali model klient/server.
C Program na vytvorenie servera
Server.c
C
// Server side C program to demonstrate Socket> // programming> #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);> > }> > valread = read(new_socket, buffer,> > 1024 - 1);> // subtract 1 for the null> > // terminator at the end> > printf> (> '%s
'> , buffer);> > send(new_socket, hello,> strlen> (hello), 0);> > printf> (> 'Hello message sent
'> );> > // closing the connected socket> > close(new_socket);> > // closing the listening socket> > close(server_fd);> > return> 0;> }> |
C Program na vytvorenie klienta
klient.c
C
// Client side C program to demonstrate Socket> // programming> #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> (> '
Socket creation error
'> );> > 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> (> > '
Invalid address/ Address not supported
'> );> > return> -1;> > }> > if> ((status> > = connect(client_fd, (> struct> sockaddr*)&serv_addr,> > sizeof> (serv_addr)))> > <0) {> > printf> (> '
Connection Failed
'> );> > return> -1;> > }> > send(client_fd, hello,> strlen> (hello), 0);> > printf> (> 'Hello message sent
'> );> > valread = read(client_fd, buffer,> > 1024 - 1);> // subtract 1 for the null> > // terminator at the end> > printf> (> '%s
'> , buffer);> > // closing the connected socket> > close(client_fd);> > return> 0;> }> |
Výkon
Client:Hello message sent Hello from server Server:Hello from client Hello message sent
Zostavovanie
gcc client.c -o client gcc server.c -o server
Ďalej: Programovanie soketov v C/C++: Obsluha viacerých klientov na serveri bez viacerých vlákien