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;
+}
+