Mercurial
comparison 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 |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 0:5695ef413be0 |
|---|---|
| 1 /* | |
| 2 ** server.c -- a stream socket server demo | |
| 3 */ | |
| 4 | |
| 5 #include <stdio.h> | |
| 6 #include <stdlib.h> | |
| 7 #include <unistd.h> | |
| 8 #include <errno.h> | |
| 9 #include <string.h> | |
| 10 #include <sys/types.h> | |
| 11 #include <sys/socket.h> | |
| 12 #include <netinet/in.h> | |
| 13 #include <netdb.h> | |
| 14 #include <arpa/inet.h> | |
| 15 #include <sys/wait.h> | |
| 16 #include <signal.h> | |
| 17 | |
| 18 #define PORT "6969" | |
| 19 | |
| 20 #define BACKLOG 10 // how many pending connections queue will hold | |
| 21 | |
| 22 void SigchildHandler(int s) | |
| 23 { | |
| 24 (void)s; // quiet unused variable warning | |
| 25 | |
| 26 // waitpid() might overwrite errno, so we save and restore it: | |
| 27 int saved_errno = errno; | |
| 28 | |
| 29 while(waitpid(-1, NULL, WNOHANG) > 0); | |
| 30 | |
| 31 errno = saved_errno; | |
| 32 } | |
| 33 | |
| 34 | |
| 35 void *GetInternetaddr(struct sockaddr *sa) | |
| 36 { | |
| 37 if (sa->sa_family == AF_INET) | |
| 38 { | |
| 39 return &(((struct sockaddr_in*)sa)->sin_addr); | |
| 40 } | |
| 41 | |
| 42 return &(((struct sockaddr_in6*)sa)->sin6_addr); | |
| 43 } | |
| 44 | |
| 45 int main(void) | |
| 46 { | |
| 47 int sock_fd, client_fd; | |
| 48 struct addrinfo hints, *server_infos, *free_server_info; | |
| 49 int yes = 1; // boolean | |
| 50 | |
| 51 struct sockaddr_storage client_addr; | |
| 52 socklen_t sin_size; | |
| 53 | |
| 54 char client_inet_addr[INET6_ADDRSTRLEN]; | |
| 55 | |
| 56 struct sigaction sa; | |
| 57 | |
| 58 memset(&hints, 0, sizeof(hints)); | |
| 59 hints.ai_family = AF_INET; | |
| 60 hints.ai_socktype = SOCK_STREAM; | |
| 61 hints.ai_flags = AI_PASSIVE; | |
| 62 | |
| 63 if (getaddrinfo(NULL, PORT, &hints, &server_infos) == 1) | |
| 64 { | |
| 65 perror("getaddrinfo"); | |
| 66 return 1; | |
| 67 } | |
| 68 | |
| 69 for (free_server_info = server_infos; free_server_info != NULL; free_server_info = free_server_info->ai_next) | |
| 70 { | |
| 71 if ((sock_fd = socket(free_server_info->ai_family, free_server_info->ai_socktype, free_server_info->ai_protocol)) == -1) | |
| 72 { | |
| 73 perror("socket"); | |
| 74 continue; | |
| 75 } | |
| 76 | |
| 77 if (setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) == -1) | |
| 78 { | |
| 79 perror("setsockopt"); | |
| 80 continue; | |
| 81 } | |
| 82 | |
| 83 if (bind(sock_fd, free_server_info->ai_addr, free_server_info->ai_addrlen) == -1) | |
| 84 { | |
| 85 close(sock_fd); | |
| 86 perror("setsockopt"); | |
| 87 continue; | |
| 88 } | |
| 89 | |
| 90 // binded to a open server infos; | |
| 91 break; | |
| 92 } | |
| 93 | |
| 94 freeaddrinfo(server_infos); | |
| 95 | |
| 96 if (free_server_info == NULL) | |
| 97 { | |
| 98 perror("No free server"); | |
| 99 return 1; | |
| 100 } | |
| 101 | |
| 102 if (listen(sock_fd, BACKLOG) != 0) | |
| 103 { | |
| 104 perror("listen"); | |
| 105 return 1; | |
| 106 } | |
| 107 | |
| 108 sa.sa_handler = SigchildHandler; // reap all dead processes | |
| 109 sigemptyset(&sa.sa_mask); | |
| 110 sa.sa_flags = SA_RESTART; | |
| 111 if (sigaction(SIGCHLD, &sa, NULL) == -1) { | |
| 112 perror("sigaction"); | |
| 113 exit(1); | |
| 114 } | |
| 115 | |
| 116 printf("server: waiting for connections...\n"); | |
| 117 | |
| 118 char *response = | |
| 119 "HTTP/1.1 OK %s\r\n" | |
| 120 "Content-Type: text/txt\r\n" | |
| 121 "Content-Length: 13\r\n" | |
| 122 "Connection: close\r\n" | |
| 123 "\r\n" | |
| 124 "Hello, world!"; | |
| 125 | |
| 126 while (1) | |
| 127 { | |
| 128 sin_size = sizeof(client_addr); | |
| 129 client_fd = accept(sock_fd, (struct sockaddr *)&client_addr, &sin_size); | |
| 130 | |
| 131 if (client_fd == -1) | |
| 132 { | |
| 133 perror("accept"); | |
| 134 continue; | |
| 135 } | |
| 136 | |
| 137 inet_ntop( | |
| 138 client_addr.ss_family, | |
| 139 GetInternetaddr((struct sockaddr *)&client_addr), | |
| 140 client_inet_addr, sizeof client_inet_addr); | |
| 141 | |
| 142 printf("server: got connection from %s\n", client_inet_addr); | |
| 143 | |
| 144 // Create a child process | |
| 145 if (!fork()) | |
| 146 { | |
| 147 close(sock_fd); | |
| 148 if (send(client_fd, response, strlen(response), 0) == -1) | |
| 149 { | |
| 150 perror("send"); | |
| 151 continue; | |
| 152 } | |
| 153 close(client_fd); | |
| 154 exit(0); | |
| 155 } | |
| 156 | |
| 157 close(client_fd); | |
| 158 } | |
| 159 | |
| 160 return 0; | |
| 161 } | |
| 162 |