87 struct sockaddr_in addr;
90 server_fd = socket(AF_INET, SOCK_STREAM, 0);
96 setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt,
sizeof(opt));
98 memset(&addr, 0,
sizeof(addr));
99 addr.sin_family = AF_INET;
100 addr.sin_addr.s_addr = INADDR_ANY;
101 addr.sin_port = htons((uint16_t)port);
103 if (bind(server_fd, (
struct sockaddr *)&addr,
sizeof(addr)) < 0) {
108 if (listen(server_fd, 128) < 0) {
132static void worker_loop(
int server_fd,
int worker_id,
int conns_per_worker) {
133 printf(
"[ワーカー %d, PID %lu] 起動完了、接続待機\n", worker_id, (
unsigned long)
get_pid());
135 if (conns_per_worker == 1) {
137 struct sockaddr_in client_addr;
142 addr_len =
sizeof(client_addr);
143 client_fd = accept(server_fd, (
struct sockaddr *)&client_addr, &addr_len);
146 if (errno == EINTR) {
153 printf(
"[ワーカー %d] クライアント接続\n", worker_id);
155 printf(
"[ワーカー %d] 次の接続待機\n", worker_id);
159 struct epoll_event ev;
162 int active_count = 0;
165 int epoll_fd = epoll_create1(0);
167 perror(
"epoll_create1");
172 ev.data.fd = server_fd;
173 if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, server_fd, &ev) < 0) {
174 perror(
"epoll_ctl add server_fd");
181 if (errno == EINTR) {
184 perror(
"epoll_wait");
188 for (
int i = 0; i < nfds; i++) {
189 int fd = events[i].data.fd;
191 if (fd == server_fd) {
193 int client_fd = accept(server_fd, NULL, NULL);
195 if (errno != EINTR) {
202 ev.data.fd = client_fd;
203 if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, client_fd, &ev) < 0) {
204 perror(
"epoll_ctl add client_fd");
210 printf(
"[ワーカー %d] 新規接続 (計 %d 接続)\n", worker_id, active_count);
213 if (active_count >= conns_per_worker) {
214 epoll_ctl(epoll_fd, EPOLL_CTL_DEL, server_fd, NULL);
222 epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fd, NULL);
225 printf(
"[ワーカー %d] 接続終了 (残 %d 接続)\n", worker_id, active_count);
228 if (!accepting && active_count < conns_per_worker) {
230 ev.data.fd = server_fd;
231 if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, server_fd, &ev) == 0) {
245 printf(
"[ワーカー %d] 終了\n", worker_id);
276 int server_fd, client_fd;
277 struct sockaddr_in addr;
278 socklen_t addr_len =
sizeof(addr);
283 sigemptyset(&sa.sa_mask);
284 sa.sa_flags = SA_RESTART;
285 sigaction(SIGCHLD, &sa, NULL);
288 printf(
"[親プロセス %lu] fork モード、ポート %d で待ち受け開始\n", (
unsigned long)
get_pid(), port);
291 client_fd = accept(server_fd, (
struct sockaddr *)&addr, &addr_len);
297 printf(
"[親プロセス] 接続受付、子プロセス生成\n");
303 }
else if (pid == 0) {
322 sigemptyset(&sa.sa_mask);
324 sigaction(SIGINT, &sa, NULL);
325 sigaction(SIGTERM, &sa, NULL);
329 sa.sa_flags = SA_RESTART;
330 sigaction(SIGCHLD, &sa, NULL);
333 printf(
"[親プロセス %lu] prefork モード、ポート %d で待ち受け開始\n", (
unsigned long)
get_pid(), port);
334 printf(
"[親プロセス] %d 個のワーカープロセスを起動 (1 ワーカーあたり最大 %d 接続)\n",
335 num_workers, conns_per_worker);
337 pid_t *worker_pids = malloc((
size_t)num_workers *
sizeof(pid_t));
343 for (
int i = 0; i < num_workers; i++) {
349 }
else if (pid == 0) {
354 worker_pids[i] = pid;
357 printf(
"[親プロセス] Ctrl+C で終了\n");
363 printf(
"\n[親プロセス] 全ワーカーを終了させます\n");
364 for (
int i = 0; i < num_workers; i++) {
365 if (worker_pids[i] > 0) {
366 kill(worker_pids[i], SIGTERM);
370 for (
int i = 0; i < num_workers; i++) {
371 if (worker_pids[i] > 0) {
372 waitpid(worker_pids[i], NULL, 0);
378 printf(
"[親プロセス] 終了\n");