Co to jest programowanie gniazdowe?
Programowanie gniazd to sposób łączenia dwóch węzłów w sieci w celu komunikowania się ze sobą. Jedno gniazdo (węzeł) nasłuchuje na określonym porcie pod adresem IP, podczas gdy drugie gniazdo łączy się z drugim, tworząc połączenie. Serwer tworzy gniazdo nasłuchiwania, podczas gdy klient łączy się z serwerem.
Diagram stanu dla modelu serwera i klienta

Diagram stanu dla modelu serwera i klienta Socket
Etapy dla serwera
Serwer jest tworzony w następujący sposób:
program powitalny Java
1. Tworzenie gniazda
int sockfd = socket(domain, type, protocol)>
- sockfd: deskryptor gniazda, liczba całkowita (jak uchwyt pliku) domena: liczba całkowita, określa domenę komunikacyjną. Używamy AF_LOCAL zgodnie z definicją w standardzie POSIX do komunikacji między procesami na tym samym hoście. Do komunikacji między procesami na różnych hostach połączonych przez IPV4 używamy AF_INET i AF_I NET 6 dla procesów połączonych przez IPV6. typ: typ komunikacji
SOCK_STREAM: TCP (niezawodny, zorientowany na połączenie)
SOCK_DGRAM: Protokół UDP (niewiarygodny, bezpołączeniowy): Wartość protokołu dla protokołu internetowego (IP), która wynosi 0. Jest to ta sama liczba, która pojawia się w polu protokołu w nagłówku IP pakietu. (więcej szczegółów można znaleźć w protokołach man)
2. Ustawia opcję
Pomaga to w manipulowaniu opcjami gniazda, do którego odnosi się deskryptor pliku sockfd. Jest to całkowicie opcjonalne, ale pomaga w ponownym wykorzystaniu adresu i portu. Zapobiega błędom takim jak: adres już używany.
int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);>
3. Zwiąż
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);>
Po utworzeniu gniazda funkcja bind wiąże gniazdo z adresem i numerem portu określonymi w adresie (niestandardowa struktura danych). W przykładowym kodzie łączymy serwer z hostem lokalnym, dlatego do określenia adresu IP używamy INADDR_ANY.
4. Słuchaj
int listen(int sockfd, int backlog);>
Przełącza gniazdo serwera w tryb pasywny, w którym czeka, aż klient zbliży się do serwera w celu nawiązania połączenia. Backlog określa maksymalną długość do jakiej może urosnąć kolejka oczekujących połączeń dla sockfd. Jeśli żądanie połączenia nadejdzie, gdy kolejka jest pełna, klient może otrzymać błąd ze wskazaniem ECONNREFUSED.
5. Zaakceptuj
int new_socket= accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);>
Wyodrębnia pierwsze żądanie połączenia z kolejki oczekujących połączeń dla gniazda nasłuchującego, sockfd, tworzy nowe połączone gniazdo i zwraca nowy deskryptor pliku odnoszący się do tego gniazda. W tym momencie zostaje nawiązane połączenie pomiędzy klientem a serwerem i serwer jest gotowy do przesyłania danych.
Etapy dla Klienta
1. Podłączenie do gniazda: Dokładnie tak samo, jak przy tworzeniu gniazda serwera
2. Połącz: Wywołanie systemowe connect() łączy gniazdo określone przez deskryptor pliku sockfd z adresem określonym przez adres. Adres i port serwera podano w adresie.
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);>
Realizacja
Tutaj wymieniamy jedną wiadomość powitalną między serwerem a klientem, aby zademonstrować model klient/serwer.
Program C do tworzenia serwera
Serwer.c
C
jak uruchomić skrypt na Linuksie
// 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;> }> |
>
>
Program C do tworzenia 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;> }> |
przechodzenie przez pocztę
>
>
Wyjście
Client:Hello message sent Hello from server Server:Hello from client Hello message sent>
Kompilowanie
gcc client.c -o client gcc server.c -o server>
Dalej: Programowanie gniazd w C/C++: Obsługa wielu klientów na serwerze bez wielowątkowości