Mercurial
diff seobeo/main.c @ 0:5695ef413be0
Initialized mono repo with bazels with few examples.
| author | June Park <parkjune1995@gmail.com> |
|---|---|
| date | Tue, 23 Sep 2025 10:05:25 -0700 |
| parents | |
| children | adcfad6e86fb |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/seobeo/main.c Tue Sep 23 10:05:25 2025 -0700 @@ -0,0 +1,162 @@ +/* +** server.c -- a stream socket server demo +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <errno.h> +#include <string.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <netdb.h> +#include <arpa/inet.h> +#include <sys/wait.h> +#include <signal.h> + +#define PORT "6969" + +#define BACKLOG 10 // how many pending connections queue will hold + +void SigchildHandler(int s) +{ + (void)s; // quiet unused variable warning + + // waitpid() might overwrite errno, so we save and restore it: + int saved_errno = errno; + + while(waitpid(-1, NULL, WNOHANG) > 0); + + errno = saved_errno; +} + + +void *GetInternetaddr(struct sockaddr *sa) +{ + if (sa->sa_family == AF_INET) + { + return &(((struct sockaddr_in*)sa)->sin_addr); + } + + return &(((struct sockaddr_in6*)sa)->sin6_addr); +} + +int main(void) +{ + int sock_fd, client_fd; + struct addrinfo hints, *server_infos, *free_server_info; + int yes = 1; // boolean + + struct sockaddr_storage client_addr; + socklen_t sin_size; + + char client_inet_addr[INET6_ADDRSTRLEN]; + + struct sigaction sa; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_PASSIVE; + + if (getaddrinfo(NULL, PORT, &hints, &server_infos) == 1) + { + perror("getaddrinfo"); + return 1; + } + + for (free_server_info = server_infos; free_server_info != NULL; free_server_info = free_server_info->ai_next) + { + if ((sock_fd = socket(free_server_info->ai_family, free_server_info->ai_socktype, free_server_info->ai_protocol)) == -1) + { + perror("socket"); + continue; + } + + if (setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) == -1) + { + perror("setsockopt"); + continue; + } + + if (bind(sock_fd, free_server_info->ai_addr, free_server_info->ai_addrlen) == -1) + { + close(sock_fd); + perror("setsockopt"); + continue; + } + + // binded to a open server infos; + break; + } + + freeaddrinfo(server_infos); + + if (free_server_info == NULL) + { + perror("No free server"); + return 1; + } + + if (listen(sock_fd, BACKLOG) != 0) + { + perror("listen"); + return 1; + } + + sa.sa_handler = SigchildHandler; // reap all dead processes + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_RESTART; + if (sigaction(SIGCHLD, &sa, NULL) == -1) { + perror("sigaction"); + exit(1); + } + + printf("server: waiting for connections...\n"); + + char *response = + "HTTP/1.1 OK %s\r\n" + "Content-Type: text/txt\r\n" + "Content-Length: 13\r\n" + "Connection: close\r\n" + "\r\n" + "Hello, world!"; + + while (1) + { + sin_size = sizeof(client_addr); + client_fd = accept(sock_fd, (struct sockaddr *)&client_addr, &sin_size); + + if (client_fd == -1) + { + perror("accept"); + continue; + } + + inet_ntop( + client_addr.ss_family, + GetInternetaddr((struct sockaddr *)&client_addr), + client_inet_addr, sizeof client_inet_addr); + + printf("server: got connection from %s\n", client_inet_addr); + + // Create a child process + if (!fork()) + { + close(sock_fd); + if (send(client_fd, response, strlen(response), 0) == -1) + { + perror("send"); + continue; + } + close(client_fd); + exit(0); + } + + close(client_fd); + } + + return 0; +} +