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