Graceful Shutdown
When working with network programs in C, it is essential to handle the shutdown process carefully to avoid resource leaks and undefined behavior. Properly closing sockets and cleaning up resources ensures that your application does not leave open file descriptors, which could eventually exhaust system resources and prevent new connections from being established. When a socket is no longer needed, you must signal the end of communication, gracefully close the connection, and release any resources associated with it. This involves using the shutdown() function to indicate that you have finished sending or receiving data, followed by the close() function to free the socket descriptor.
graceful_shutdown.c
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #include <sys/socket.h> #include <netinet/in.h> #define PORT 8080 void run_server() { int server_fd, client_fd; struct sockaddr_in address; socklen_t addrlen = sizeof(address); char buffer[1024] = {0}; server_fd = socket(AF_INET, SOCK_STREAM, 0); if (server_fd < 0) { perror("Server socket failed"); exit(EXIT_FAILURE); } address.sin_family = AF_INET; address.sin_addr.s_addr = INADDR_ANY; address.sin_port = htons(PORT); if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) { perror("Bind failed"); close(server_fd); exit(EXIT_FAILURE); } if (listen(server_fd, 1) < 0) { perror("Listen failed"); close(server_fd); exit(EXIT_FAILURE); } printf("Server listening on port %d...\n", PORT); client_fd = accept(server_fd, (struct sockaddr *)&address, &addrlen); if (client_fd < 0) { perror("Accept failed"); close(server_fd); exit(EXIT_FAILURE); } int valread = read(client_fd, buffer, sizeof(buffer)); printf("Server received: %s\n", buffer); // Graceful shutdown: stop further sends and receives shutdown(client_fd, SHUT_RDWR); close(client_fd); close(server_fd); printf("Server sockets closed gracefully.\n"); } void run_client() { int sock; struct sockaddr_in serv_addr; char *message = "Hello, server!"; sock = socket(AF_INET, SOCK_STREAM, 0); if (sock < 0) { perror("Client socket failed"); exit(EXIT_FAILURE); } serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(PORT); if (inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr) <= 0) { perror("Invalid address"); close(sock); exit(EXIT_FAILURE); } if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { perror("Connection failed"); close(sock); exit(EXIT_FAILURE); } send(sock, message, strlen(message), 0); // Graceful shutdown: stop further sends and receives shutdown(sock, SHUT_RDWR); close(sock); printf("Client socket closed gracefully.\n"); } int main(int argc, char const *argv[]) { if (argc != 2) { printf("Usage: %s [server|client]\n", argv[0]); return 1; } if (strcmp(argv[1], "server") == 0) { run_server(); } else if (strcmp(argv[1], "client") == 0) { run_client(); } else { printf("Unknown role: %s\n", argv[1]); return 1; } return 0; }
This program shows a simple TCP client–server interaction in C. The server creates a socket, binds to port 8080, listens for a connection, accepts a client, reads the message, and then shuts down cleanly. The client creates a socket, connects to 127.0.0.1:8080, sends a short message, and closes the connection. Together, they demonstrate the basic TCP workflow: socket creation, connection, data transfer, and graceful shutdown.
This example handles only one client and does not echo the message back to the client. In a real TCP echo server, the server would send the received data back before closing the connection.
Kiitos palautteestasi!
Kysy tekoälyä
Kysy tekoälyä
Kysy mitä tahansa tai kokeile jotakin ehdotetuista kysymyksistä aloittaaksesi keskustelumme
Mahtavaa!
Completion arvosana parantunut arvoon 8.33
Graceful Shutdown
Pyyhkäise näyttääksesi valikon
When working with network programs in C, it is essential to handle the shutdown process carefully to avoid resource leaks and undefined behavior. Properly closing sockets and cleaning up resources ensures that your application does not leave open file descriptors, which could eventually exhaust system resources and prevent new connections from being established. When a socket is no longer needed, you must signal the end of communication, gracefully close the connection, and release any resources associated with it. This involves using the shutdown() function to indicate that you have finished sending or receiving data, followed by the close() function to free the socket descriptor.
graceful_shutdown.c
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #include <sys/socket.h> #include <netinet/in.h> #define PORT 8080 void run_server() { int server_fd, client_fd; struct sockaddr_in address; socklen_t addrlen = sizeof(address); char buffer[1024] = {0}; server_fd = socket(AF_INET, SOCK_STREAM, 0); if (server_fd < 0) { perror("Server socket failed"); exit(EXIT_FAILURE); } address.sin_family = AF_INET; address.sin_addr.s_addr = INADDR_ANY; address.sin_port = htons(PORT); if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) { perror("Bind failed"); close(server_fd); exit(EXIT_FAILURE); } if (listen(server_fd, 1) < 0) { perror("Listen failed"); close(server_fd); exit(EXIT_FAILURE); } printf("Server listening on port %d...\n", PORT); client_fd = accept(server_fd, (struct sockaddr *)&address, &addrlen); if (client_fd < 0) { perror("Accept failed"); close(server_fd); exit(EXIT_FAILURE); } int valread = read(client_fd, buffer, sizeof(buffer)); printf("Server received: %s\n", buffer); // Graceful shutdown: stop further sends and receives shutdown(client_fd, SHUT_RDWR); close(client_fd); close(server_fd); printf("Server sockets closed gracefully.\n"); } void run_client() { int sock; struct sockaddr_in serv_addr; char *message = "Hello, server!"; sock = socket(AF_INET, SOCK_STREAM, 0); if (sock < 0) { perror("Client socket failed"); exit(EXIT_FAILURE); } serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(PORT); if (inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr) <= 0) { perror("Invalid address"); close(sock); exit(EXIT_FAILURE); } if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { perror("Connection failed"); close(sock); exit(EXIT_FAILURE); } send(sock, message, strlen(message), 0); // Graceful shutdown: stop further sends and receives shutdown(sock, SHUT_RDWR); close(sock); printf("Client socket closed gracefully.\n"); } int main(int argc, char const *argv[]) { if (argc != 2) { printf("Usage: %s [server|client]\n", argv[0]); return 1; } if (strcmp(argv[1], "server") == 0) { run_server(); } else if (strcmp(argv[1], "client") == 0) { run_client(); } else { printf("Unknown role: %s\n", argv[1]); return 1; } return 0; }
This program shows a simple TCP client–server interaction in C. The server creates a socket, binds to port 8080, listens for a connection, accepts a client, reads the message, and then shuts down cleanly. The client creates a socket, connects to 127.0.0.1:8080, sends a short message, and closes the connection. Together, they demonstrate the basic TCP workflow: socket creation, connection, data transfer, and graceful shutdown.
This example handles only one client and does not echo the message back to the client. In a real TCP echo server, the server would send the received data back before closing the connection.
Kiitos palautteestasi!