Server 0
Server 0
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