Programiranje vtičnic je način povezovanja dveh vozlišč v omrežju za medsebojno komunikacijo. Ena vtičnica (vozlišče) posluša določena vrata na IP-ju, medtem ko druga vtičnica doseže drugo in vzpostavi povezavo. Strežnik oblikuje vtičnico poslušalca, medtem ko se odjemalec obrne na strežnik.
Programiranje vtičnic se pogosto uporablja v aplikacijah za neposredno sporočanje, binarnem pretakanju in sodelovanju pri dokumentih, platformah za spletno pretakanje itd.
Primer
V tem programu C si izmenjujemo eno pozdravno sporočilo med strežnikom in odjemalcem, da prikažemo model odjemalec/strežnik.
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('%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; }
stranka.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; }
Prevajanje
gcc client.c -o clientgcc server.c -o server
Izhod
Client:Hello message sentHello from serverServer:Hello from clientHello message sentKomponente programiranja vtičnic
1. Vtičnice
Vtičnice so ena od osrednjih komponent, ki jih program uporablja za dostop do omrežja za komunikacijo z drugimi procesi/vozlišči prek omrežja. To je preprosto kombinacija naslova IP in številke vrat, ki deluje kot končna točka za komunikacijo.
Primer: 192.168.1.1:8080 kjer dva dela, ločena z dvopičjem, predstavljata naslov IP (192.168.1.1) in številka vrat (8080).
Vrste vtičnic:
- TCP vtičnica (pretočna vtičnica): Zagotavlja zanesljivo komunikacijo na podlagi povezave (tj. protokol TCP ).
- Vtičnica UDP (datagramska vtičnica): Omogoča hitrejšo komunikacijo brez povezave, vendar nezanesljivo (tj. protokol UDP ).
2. Model odjemalec-strežnik
The model odjemalec-strežnik se nanaša na arhitekturo, ki se uporablja pri programiranju vtičnic, kjer odjemalec in strežnik komunicirata drug z drugim za izmenjavo informacij ali storitev. Ta arhitektura omogoča odjemalcu, da pošilja storitvene zahteve, strežniku pa obdelavo in pošiljanje odgovorov na te storitvene zahteve.
Diagram stanja za model strežnika in odjemalca
Diagram stanja za model strežnika in odjemalca vtičniceProgramiranje vtičnic v C je zmogljiv način za upravljanje omrežne komunikacije.
Ustvarjanje procesa na strani strežnika
Strežnik se ustvari po naslednjih korakih:
kako pretvoriti char v niz java
1. Izdelava vtičnice
Ta korak vključuje ustvarjanje vtičnice s funkcijo socket().
Parametri:
- sockfd: deskriptor vtičnice celo število (kot ročaj datoteke)
- domena: celo število določa komunikacijsko domeno. Za komunikacijo med procesi na istem gostitelju uporabljamo AF_ LOCAL, kot je definirano v standardu POSIX. Za komunikacijo med procesi na različnih gostiteljih, povezanih z IPV4, uporabljamo AF_INET in AF_I NET 6 za procese, povezane z IPV6.
- vrsta: vrsta komunikacije
SOCK_STREAM: TCP (usmerjen na zanesljivo povezavo)
SOCK_DGRAM: UDP (nezanesljivo brez povezave) - protokol: Vrednost protokola za internetni protokol (IP), ki je 0. To je ista številka, ki se pojavi v polju protokola v glavi IP paketa. (man protokoli za več podrobnosti)
sockfd = socket(domain type protocol)
2. Nastavite možnost vtičnice
To pomaga pri manipulaciji z možnostmi za vtičnico, ki jo navaja deskriptor datoteke sockfd. To je povsem neobvezno, vendar pomaga pri ponovni uporabi naslova in vrat. Preprečuje napako, kot je: naslov je že v uporabi.
Csetsockopt(sockfd level optname optval socklen_t optlen);
3. Zavežite
Po izdelavi vtičnice funkcija bind() poveže vtičnico z naslovom in številko vrat, določeno v addr(podatkovna struktura po meri). V primeru kode povežemo strežnik z lokalnim gostiteljem, zato uporabimo INADDR_ANY za določitev naslova IP.
C++bind(sockfd sockaddr *addr socklen_t addrlen);
Parametri:
- sockfd : deskriptor datoteke socket, ustvarjen s funkcijo socket().
- naslov : kazalec na strukturo sockaddr, ki vsebuje naslov IP in številko vrat za povezovanje vtičnice.
- addrlen : dolžina strukture addr.
4. Poslušaj
V tem koraku strežnik uporabi funkcijo listen(), ki strežniško vtičnico postavi v pasivni način, kjer čaka, da se odjemalec približa strežniku, da vzpostavi povezavo. Zaostanek določa največjo dolžino, do katere lahko naraste čakalna vrsta čakajočih povezav za sockfd. Če zahteva za povezavo prispe, ko je čakalna vrsta polna, lahko odjemalec prejme napako z navedbo ECONNREFUSED.
Clisten(sockfd backlog);
Parametri :
- sockfd : deskriptor datoteke socket, ustvarjen s funkcijo socket().
- zaostanek : število, ki predstavlja velikost čakalne vrste, v kateri so čakajoče povezave, medtem ko strežnik čaka na sprejem povezave.
5. Sprejmi
V tem koraku strežnik ekstrahira prvo zahtevo za povezavo iz čakalne vrste čakajočih povezav za poslušajočo vtičnico sockfd ustvari novo povezano vtičnico z uporabo sprejeti() in vrne nov deskriptor datoteke, ki se nanaša na to vtičnico. Na tej točki je vzpostavljena povezava med odjemalcem in strežnikom in sta pripravljena za prenos podatkov.
Cnew_socket= accept(sockfd sockaddr *addr socklen_t *addrlen);
Parametri:
- sockfd : deskriptor datoteke vtičnice, ki ga vrneta socket() in bind().
- naslov : kazalec na strukturo sockaddr, ki bo vsebovala odjemalčev naslov IP in številko vrat.
- addrlen : kazalec na spremenljivko, ki določa dolžino strukture naslova.
6. Pošlji/prejmi
V tem koraku lahko strežnik pošilja ali prejema podatke od odjemalca.
Pošlji(): za pošiljanje podatkov stranki
Csend(sockfd *buf len flags);
Parametri:
- sockfd : deskriptor datoteke socket, ki ga vrne funkcija socket().
- buf : kazalec na medpomnilnik, ki vsebuje podatke za pošiljanje.
- samo : število bajtov podatkov za pošiljanje.
- zastave : celo število, ki določa različne možnosti za pošiljanje podatkov, običajno 0 se uporablja za privzeto vedenje.
Prejmi(): za prejem podatkov od naročnika.
Crecv( sockfd *buf len flags);
Parametri:
- sockfd : deskriptor datoteke socket, ki ga vrne funkcija socket().
- buf : kazalec na medpomnilnik, ki vsebuje podatke za shranjevanje.
- samo : število bajtov podatkov za pošiljanje.
- zastave : celo število, ki določa različne možnosti za pošiljanje podatkov, običajno 0 se uporablja za privzeto vedenje.
6. Zapri
Po končani izmenjavi informacij strežnik zapre vtičnico s funkcijo close() in sprosti sistemske vire.
Cclose(fd);
Parametri:
- fd: datotečni deskriptor vtičnice.
Ustvarjanje procesa na strani odjemalca
Sledite spodnjim korakom za ustvarjanje postopka na strani odjemalca:
1. Priključek vtičnice
Ta korak vključuje ustvarjanje vtičnice, ki se izvede na enak način kot ustvarjanje vtičnice strežnika
2. Povežite se
Sistemski klic connect() poveže vtičnico, na katero se sklicuje deskriptor datoteke sockfd, z naslovom, ki ga določa addr. Naslov in vrata strežnika so določena v naslovu.
C++connect(sockfd sockaddr *addr socklen_t addrlen);
Parametri
- sockfd : deskriptor datoteke socket, ki ga vrne funkcija socket().
- naslov : kazalec na strukturo sockaddr, ki vsebuje naslov IP strežnika in številko vrat.
- addrlen : velikost naslova
3. Pošlji/prejmi
V tem koraku lahko odjemalec pošlje ali prejme podatke s strežnika, kar se izvede s funkcijama send() in recieve(), podobno kot strežnik pošilja/prejme podatke od odjemalca.
4. Zaprite
Ko je izmenjava informacij končana, mora odjemalec zapreti ustvarjeno vtičnico in sprostiti sistemske vire s funkcijo close() na enak način kot strežnik.
Pogoste težave in njihovi popravki pri programiranju vtičnic
- Napake povezave: Da bi se izognili napakam pri povezovanju, moramo zagotoviti, da se odjemalec poskuša povezati s pravilnim IP naslov in vrata .
- Napake pri povezovanju vrat: Te napake se pojavijo, ko vrata že uporablja druga aplikacija, v tem scenariju povezava s temi vrati ne bo uspela. Poskusite uporabiti druga vrata ali zaprite prejšnjo aplikacijo prek vrat.
- Blokiranje vtičnic: Privzeto so vtičnice blokirane. To pomeni, da bodo klici, kot sta accept() ali recv(), čakali neskončno dolgo, če ni povezave ali podatkov odjemalca. Po potrebi lahko vtičnico nastavite na način brez blokiranja.