comparison seobeo/main.c @ 1:adcfad6e86fb

Updated naming and separated out some logic within seobeo.
author June Park <parkjune1995@gmail.com>
date Wed, 24 Sep 2025 09:11:20 -0700
parents 5695ef413be0
children 2758f5527d2b
comparison
equal deleted inserted replaced
0:5695ef413be0 1:adcfad6e86fb
1 /* 1 /*
2 ** server.c -- a stream socket server demo 2 ** server.c -- a stream socket server demo
3 */ 3 */
4 4
5 #include <stdio.h> 5 #include "seobeo/seobeo.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 6
22 void SigchildHandler(int s) 7 void SigchildHandler(int s)
23 { 8 {
24 (void)s; // quiet unused variable warning 9 (void)s; // quiet unused variable warning
25 10
40 } 25 }
41 26
42 return &(((struct sockaddr_in6*)sa)->sin6_addr); 27 return &(((struct sockaddr_in6*)sa)->sin6_addr);
43 } 28 }
44 29
30 void HandleClientRequest(int client_fd)
31 {
32 FILE *file = fopen("seobeo/index.html", "rb");
33 if (!file) {
34 perror("fopen");
35 return;
36 }
37
38 fseek(file, 0, SEEK_END);
39 size_t size = ftell(file);
40 fseek(file, 0, SEEK_SET);
41
42 char *data = malloc(size);
43 fread(data, 1, size, file);
44 fclose(file);
45
46 char *header = malloc(100);
47 sprintf(
48 header,
49 "HTTP/1.1 200 OK\r\n"
50 "Content-Type: text/html\r\n"
51 "Content-Length: %zu\r\n"
52 "Connection: close\r\n"
53 "\r\n",
54 size
55 );
56
57 send(client_fd, header, strlen(header), 0);
58 ssize_t total_sent = 0;
59 while (total_sent < size)
60 {
61 ssize_t sent = send(client_fd, data + total_sent, size - total_sent, 0);
62 if (sent <= 0) break;
63 total_sent += sent;
64 }
65
66 close(client_fd);
67 }
68
45 int main(void) 69 int main(void)
46 { 70 {
47 int sock_fd, client_fd; 71 int32 client_fd;
48 struct addrinfo hints, *server_infos, *free_server_info;
49 int yes = 1; // boolean
50
51 struct sockaddr_storage client_addr; 72 struct sockaddr_storage client_addr;
52 socklen_t sin_size; 73 socklen_t sin_size;
53 74
54 char client_inet_addr[INET6_ADDRSTRLEN]; 75 char client_inet_addr[INET6_ADDRSTRLEN];
55 76
56 struct sigaction sa; 77 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 78
108 sa.sa_handler = SigchildHandler; // reap all dead processes 79 sa.sa_handler = SigchildHandler; // reap all dead processes
109 sigemptyset(&sa.sa_mask); 80 sigemptyset(&sa.sa_mask);
110 sa.sa_flags = SA_RESTART; 81 sa.sa_flags = SA_RESTART;
111 if (sigaction(SIGCHLD, &sa, NULL) == -1) { 82 if (sigaction(SIGCHLD, &sa, NULL) == -1) {
112 perror("sigaction"); 83 perror("sigaction");
113 exit(1); 84 exit(1);
114 } 85 }
115 86
87 int sock_fd = Seobeo_CreateSocket(1, "6969", 10);
88
116 printf("server: waiting for connections...\n"); 89 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 90
126 while (1) 91 while (1)
127 { 92 {
128 sin_size = sizeof(client_addr); 93 sin_size = sizeof(client_addr);
129 client_fd = accept(sock_fd, (struct sockaddr *)&client_addr, &sin_size); 94 client_fd = accept(sock_fd, (struct sockaddr *)&client_addr, &sin_size);
130 95
131 if (client_fd == -1) 96 if (client_fd == -1)
132 { 97 {
133 perror("accept"); 98 perror("accept");
134 continue; 99 break;
135 } 100 }
136 101
137 inet_ntop( 102 inet_ntop(
138 client_addr.ss_family, 103 client_addr.ss_family,
139 GetInternetaddr((struct sockaddr *)&client_addr), 104 GetInternetaddr((struct sockaddr *)&client_addr),
143 108
144 // Create a child process 109 // Create a child process
145 if (!fork()) 110 if (!fork())
146 { 111 {
147 close(sock_fd); 112 close(sock_fd);
148 if (send(client_fd, response, strlen(response), 0) == -1) 113 HandleClientRequest(client_fd);
149 {
150 perror("send");
151 continue;
152 }
153 close(client_fd);
154 exit(0); 114 exit(0);
155 } 115 }
156 116
157 close(client_fd); 117 close(client_fd);
158 } 118 }