comparison seobeo/example.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
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 "3490" // the port users will be connecting to
19
20 #define BACKLOG 10 // how many pending connections queue will hold
21
22 void sigchld_handler(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 // get sockaddr, IPv4 or IPv6:
36 void *get_in_addr(struct sockaddr *sa)
37 {
38 if (sa->sa_family == AF_INET) {
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 // listen on sock_fd, new connection on new_fd
48 int sockfd, new_fd;
49 struct addrinfo hints, *servinfo, *p;
50 struct sockaddr_storage their_addr; // connector's address info
51 socklen_t sin_size;
52 struct sigaction sa;
53 int yes=1;
54 char s[INET6_ADDRSTRLEN];
55 int rv;
56
57 memset(&hints, 0, sizeof hints);
58 hints.ai_family = AF_INET;
59 hints.ai_socktype = SOCK_STREAM;
60 hints.ai_flags = AI_PASSIVE; // use my IP
61
62 if ((rv = getaddrinfo(NULL, PORT, &hints, &servinfo)) != 0) {
63 fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
64 return 1;
65 }
66
67 // loop through all the results and bind to the first we can
68 for(p = servinfo; p != NULL; p = p->ai_next) {
69 if ((sockfd = socket(p->ai_family, p->ai_socktype,
70 p->ai_protocol)) == -1) {
71 perror("server: socket");
72 continue;
73 }
74
75 if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes,
76 sizeof(int)) == -1) {
77 perror("setsockopt");
78 exit(1);
79 }
80
81 if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
82 close(sockfd);
83 perror("server: bind");
84 continue;
85 }
86
87 break;
88 }
89
90 freeaddrinfo(servinfo); // all done with this structure
91
92 if (p == NULL) {
93 fprintf(stderr, "server: failed to bind\n");
94 exit(1);
95 }
96
97 if (listen(sockfd, BACKLOG) == -1) {
98 perror("listen");
99 exit(1);
100 }
101
102 sa.sa_handler = sigchld_handler; // reap all dead processes
103 sigemptyset(&sa.sa_mask);
104 sa.sa_flags = SA_RESTART;
105 if (sigaction(SIGCHLD, &sa, NULL) == -1) {
106 perror("sigaction");
107 exit(1);
108 }
109
110 printf("server: waiting for connections...\n");
111
112 while(1) { // main accept() loop
113 sin_size = sizeof their_addr;
114 new_fd = accept(sockfd, (struct sockaddr *)&their_addr,
115 &sin_size);
116 if (new_fd == -1) {
117 perror("accept");
118 continue;
119 }
120
121 inet_ntop(their_addr.ss_family,
122 get_in_addr((struct sockaddr *)&their_addr),
123 s, sizeof s);
124 printf("server: got connection from %s\n", s);
125
126 char *yo = "HTTP/1.1 OK %s\r\n"
127 "Content-Type: text/txt\r\n"
128 "Content-Length: 13\r\n"
129 "Connection: close\r\n"
130 "\r\n"
131 "Hello, world!";
132
133 if (!fork()) { // this is the child process
134 close(sockfd); // child doesn't need the listener
135 if (send(new_fd,
136 "HTTP/1.1 OK %s\r\n"
137 "Content-Type: text/txt\r\n"
138 "Content-Length: 13\r\n"
139 "Connection: close\r\n"
140 "\r\n"
141 "Hello, world!"
142 , strlen(yo), 0) == -1)
143 perror("send");
144 close(new_fd);
145 exit(0);
146 }
147 close(new_fd); // parent doesn't need this
148 }
149
150 return 0;
151 }