0% found this document useful (0 votes)
32 views5 pages

Server 0

This C code implements a concurrent server that handles client connections by forking child processes. It sets up signal handling for the SIGCHLD signal to wait for child processes. When a client connects, it forks to create a child process that handles the request by forking twice more to run grep and sort commands on the request and send the output back to the client. The parent closes active sockets and waits for children to finish.

Uploaded by

bull rose
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
32 views5 pages

Server 0

This C code implements a concurrent server that handles client connections by forking child processes. It sets up signal handling for the SIGCHLD signal to wait for child processes. When a client connects, it forks to create a child process that handles the request by forking twice more to run grep and sort commands on the request and send the output back to the client. The parent closes active sockets and waits for children to finish.

Uploaded by

bull rose
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 5

C:\Users\dinar\Downloads\server-concurrent-td-connreuse.

c 1
1 #define _POSIX_C_SOURCE 200809L
2 #include <stdio.h>
3 #include <errno.h>
4 #include <stdlib.h>
5 #include <sys/wait.h>
6 #include <fcntl.h>
7 #include <string.h>
8 #include <unistd.h>
9 #include <signal.h>
10 #include <sys/types.h>
11 #include <sys/socket.h>
12 #include <netdb.h>
13 #include <netinet/in.h>
14 #ifdef USE_LIBUNISTRING
15 # include <unistr.h> /* per libunistring */
16 #endif
17 #include "utils.h"
18 #include "rxb.h"
19
20 #define MAX_REQUEST_SIZE (64 * 1024)
21
22
23 /* Gestore del segnale SIGCHLD */
24 void handler(int signo)
25 {
26 int status;
27
28 (void)signo;
29
30 /* gestisco tutti i figli terminati */
31 while (waitpid(-1, &status, WNOHANG) > 0)
32 continue;
33 }
34
35
36 int main(int argc, char **argv)
37 {
38 struct addrinfo hints, *res;
39 int err, sd, ns, pid, on;
40 struct sigaction sa;
41
42 /* Controllo argomenti */
43 if (argc != 2) {
44 fprintf(stderr, "Uso: %s porta\n", argv[0]);
45 exit(EXIT_FAILURE);
46 }
47
48 /* Ignoro SIGPIPE */
49 signal(SIGPIPE, SIG_IGN);
50
51 sigemptyset(&sa.sa_mask);
52 sa.sa_flags = SA_RESTART;
53 sa.sa_handler = handler;
C:\Users\dinar\Downloads\server-concurrent-td-connreuse.c 2
54
55 if (sigaction(SIGCHLD, &sa, NULL) == -1) {
56 perror("sigaction");
57 exit(EXIT_FAILURE);
58 }
59
60 memset(&hints, 0, sizeof(hints));
61 hints.ai_family = AF_UNSPEC;
62 hints.ai_socktype = SOCK_STREAM;
63 hints.ai_flags = AI_PASSIVE;
64
65 if ((err = getaddrinfo(NULL, argv[1], &hints, &res)) != 0) {
66 fprintf(stderr, "Errore setup indirizzo bind: %s\n" , gai_strerror
(err));
67 exit(EXIT_FAILURE);
68 }
69
70 if ((sd = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) <
0) {
71 perror("Errore in socket");
72 exit(EXIT_FAILURE);
73 }
74
75 on = 1;
76 if (setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) {
77 perror("setsockopt");
78 exit(EXIT_FAILURE);
79 }
80
81 if (bind(sd, res->ai_addr, res->ai_addrlen) < 0) {
82 perror("Errore in bind");
83 exit(EXIT_FAILURE);
84 }
85
86 freeaddrinfo(res);
87
88 if (listen(sd, SOMAXCONN)<0){
89 perror("listen");
90 exit(EXIT_FAILURE);
91 }
92
93 /* Attendo i client... */
94 for (;;){
95 printf("Server in ascolto...\n");
96
97 if ((ns = accept(sd, NULL, NULL)) < 0) {
98 perror("accept");
99 exit(EXIT_FAILURE);
100 }
101
102 /* Generazione di un figlio */
103 if ((pid = fork()) < 0) {
104 perror("fork");
C:\Users\dinar\Downloads\server-concurrent-td-connreuse.c 3
105 exit(EXIT_FAILURE);
106 } else if (pid == 0) {
107 int pid_n1, pid_n2, pipe_n1n2[2], status;
108 const char *end_request = "\n--- END REQUEST ---\n";
109 rxb_t rxb;
110
111 /* figlio */
112 close(sd);
113
114 /* Disabilito gestore SIGCHLD */
115 memset(&sa, 0, sizeof(sa));
116 sigemptyset(&sa.sa_mask);
117 sa.sa_handler = SIG_DFL;
118
119 if (sigaction(SIGCHLD, &sa, NULL) == -1) {
120 perror("sigaction");
121 exit(EXIT_FAILURE);
122 }
123
124 /* Inizializzo buffer di ricezione */
125 rxb_init(&rxb, MAX_REQUEST_SIZE);
126
127 /* Avvio ciclo gestione richieste */
128 for (;;) {
129 char categoria[MAX_REQUEST_SIZE];
130 size_t categoria_len;
131 memset(categoria, 0, sizeof(categoria));
132 categoria_len = sizeof(categoria)-1;
133
134 /* Leggo richiesta da Client */
135 if (rxb_readline(&rxb, ns, categoria, &categoria_len) < 0) {
136 rxb_destroy(&rxb);
137 break;
138 }
139
140 #ifdef USE_LIBUNISTRING
141 if (u8_check((uint8_t *)categoria, categoria_len) != NULL) {
142 fprintf(stderr, "Request is not valid UTF -8!\n");
143 close(ns);
144 exit(EXIT_SUCCESS);
145 }
146 #endif
147
148 /* Creo pipe */
149 if (pipe(pipe_n1n2) < 0) {
150 perror("pipe");
151 exit(EXIT_FAILURE);
152 }
153
154 if ((pid_n1 = fork()) < 0){
155 perror("seconda fork");
156 exit(EXIT_FAILURE);
157 } else if (pid_n1 == 0){
C:\Users\dinar\Downloads\server-concurrent-td-connreuse.c 4
158 /* Nipote 1 */
159
160 /* Chiudo i descrittori che non servono */
161 close(ns);
162 close(pipe_n1n2[0]);
163
164 /* Ridireziono stdout */
165 close(1);
166 if (dup(pipe_n1n2[1]) < 0) {
167 perror("dup");
168 exit(EXIT_FAILURE);
169 }
170 close(pipe_n1n2[1]);
171
172 execlp("grep", "grep", categoria, "test.txt", (char*)
NULL);
173 perror("execlp grep");
174 exit(EXIT_FAILURE);
175 }
176
177 if ((pid_n2 = fork()) < 0){
178 perror("seconda fork");
179 exit(EXIT_FAILURE);
180 } else if (pid_n2 == 0){
181 /* Nipote 2 */
182
183 /* Chiudo descrittori non necessari */
184 close(pipe_n1n2[1]);
185
186 /* Ridireziono stdin */
187 close(0);
188 if (dup(pipe_n1n2[0]) < 0) {
189 perror("dup");
190 exit(EXIT_FAILURE);
191 }
192 close(pipe_n1n2[0]);
193
194 /* Ridireziono stdout */
195 close(1);
196 if (dup(ns) < 0) {
197 perror("dup");
198 exit(EXIT_FAILURE);
199 }
200 close(ns);
201
202 execlp("sort", "sort", "-r", "-n", (char*)NULL);
203 perror("execlp sort");
204 exit(EXIT_FAILURE);
205 }
206
207 /* Figlio */
208
209 /* Chiudo descrittori non necessari */
C:\Users\dinar\Downloads\server-concurrent-td-connreuse.c 5
210 close(pipe_n1n2[0]);
211 close(pipe_n1n2[1]);
212
213 /* Aspetto terminazione figli */
214 waitpid(pid_n1, &status, 0);
215 waitpid(pid_n2, &status, 0);
216
217 /* Mando una stringa di notifica fine richiesta */
218 if (write_all(ns, end_request, strlen(end_request)) < 0) {
219 perror("write");
220 exit(EXIT_FAILURE);
221 }
222 }
223
224 /* Chiudo la socket attiva */
225 close(ns);
226
227 /* Termino il figlio */
228 exit(EXIT_SUCCESS);
229 }
230
231 /* PADRE */
232
233 /* Chiudo la socket attiva */
234 close(ns);
235 }
236 /* Chiudo la socket passiva (just in case) */
237 close(sd);
238
239 return 0;
240 }
241

You might also like