Você está na página 1de 5

1 #include <netinet/in.

h>
2 #include <unistd.h>
3 #include <strings.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <sys/socket.h>
7 #include <arpa/inet.h>
8
9
10 /**********************************************************************
11 Template de servidor com comununcação por sockets.
12 São apresentados três tipos de abordagem:
13 - Atendimento iterativo (um clinte de cada vez)
14 - Criação de um novo processo para cada ligação estabelecida, sendo que
15 a comunicação com o cliente é tratada pelo novo processo.
16 - Criação de uma nova thread para cada ligação estabelecida, sendo que
17 a comunicação com o cliente é tratada na nova thread.
18
19 No caso de um servidor projetado para atender vários tipos de pedidos,
20 diferentes abordagens podem ser usadas para cada tipo de pedido.
21 **********************************************************************/
22
23 //Criação de socket e chamada a bind e listen
24 int my_create_server_socket(char *port);
25
26 void servidor_mono_tarefa_iterativo(int sockfd);
27 void servidor_multi_tarefa_com_threads(int sockfd);
28 void servidor_multi_tarefa_com_processos(int sockfd);
29 void servidor_multi_tarefa_com_processos_sigchld(int sockfd);
30
31 int main(int argc, char *argv[]) {
32 int sockfd;
33
34 if(argc!=2) {
35 printf("Usage: %s port_number\n",argv[0]);
36 exit(1);
37 }
38
39 sockfd = my_create_server_socket(argv[1]);
40
41 servidor_mono_tarefa_iterativo(sockfd);
42 //servidor_multi_tarefa_com_threads(sockfd);
43 //servidor_multi_tarefa_com_processos(sockfd);
44 //servidor_multi_tarefa_com_processos_sigchld(sockfd);
45
46 return(0);
47 }
48
49
50 /*************************************************************************/
51 //Assume-se que recebe um descritor de socket já com ligação estabelecida,
52 //detecta o tipo de pedido (se vários possíveis), satisfaz o pedido e
53 //fecha a ligação antes de terminar (close(s))
54 void atende_pedido(int sd) {
55
56 //comunicação com o cliente usando sd
57
58
59 close(sd);
60 }
61
62
63
64
- 1 -
65 /*************************************************************************/
66 void servidor_mono_tarefa_iterativo(int s)
67 {
68 int ns;
69
70 while(1) {
71 ns = accept(s, NULL, NULL);
72 //Verificação de erros.
73 if(ns<0) {
74 perror("accept");
75 continue;
76 }
77
78 atende_pedido(ns);
79 }
80 }
81
82
83
84
85
86
87
88
89
90 /*************************************************************************/
91 #include <signal.h>
92 #include <sys/wait.h>
93 #include <errno.h>
94
95
96 void servidor_multi_tarefa_com_processos(int s) {
97 int ns, r;
98
99 signal(SIGCHLD, SIG_IGN);
100
101 while(1) {
102 ns = accept(s, NULL, NULL);
103 if(ns < 0) {
104 perror("accept");
105 continue;
106 }
107
108 r = fork();
109 if(r == 0) {
110 atende_pedido(ns);
111 exit(0);
112 }
113 else if(r < 0) {
114 //Não conseguiu criar novo processo. Atende em modo iterativo
115 atende_pedido(ns);
116 }
117 else
118 close(ns);
119
120 }
121 }
122
123
124
125
126
127
128
- 2 -
129
130
131
132
133
134 /*************************************************************************/
135 #include <signal.h>
136 #include <sys/wait.h>
137 #include <errno.h>
138
139 void sigchld_handler(int signum) {
140 int pid;
141
142 do {
143 pid = waitpid(-1, NULL, WNOHANG);
144 printf("Child process %d terminated\n", pid);
145 } while( pid > 0);
146 }
147
148 void servidor_multi_tarefa_com_processos_sigchld(int s) {
149 int ns, r;
150
151 //usar o SIGCHLD para detectar a terminação dos processos filho
152 struct sigaction act;
153 act.sa_handler = sigchld_handler;
154 act.sa_flags = SA_NOCLDSTOP;
155 sigemptyset(&(act.sa_mask));
156 sigaction(SIGCHLD, &act, NULL);
157
158 while(1) {
159 ns = accept(s, NULL, NULL);
160 //pode dar-se o caso do accept ser interrompido pelo SIGCHLD (EINTR)
161 if( ns < 0) {
162 if(errno != EINTR)
163 perror("accept");
164 continue;
165 }
166
167
168 r = fork();
169 if(r == 0) {
170 atende_pedido(ns);
171 exit(0);
172 }
173 else if(r < 0) {
174 //não conseguiu criar novo processo. Atende em modo iterativo
175 atende_pedido(ns);
176 }
177 else
178 close(ns);
179
180 }
181 }
182
183
184
185
186
187
188
189
190
191
192
- 3 -
193
194 /*********************************************************************/
195 #include <pthread.h>
196
197 typedef struct {
198 int s;
199 //outras variáveis necessárias
200 } args_t;
201
202
203 void *aux(void *args) {
204 atende_pedido( ((args_t *) args)->s );
205 free(args);
206 return(NULL);
207 }
208
209
210 void servidor_multi_tarefa_com_threads(int s)
211 {
212 int ns, r;
213 pthread_t tid;
214 args_t *pargs;
215
216 while(1) {
217 ns = accept(s, NULL, NULL);
218 if(ns < 0) {
219 perror("accept");
220 continue;
221 }
222
223 pargs=malloc(sizeof(args_t));
224 pargs->s = ns;
225
226 r = pthread_create(&tid, NULL, aux, pargs) ;
227 if(r != 0) {
228 //não conseguiu criar nova thread. Atende em modo iterativo.
229 atende_pedido(ns);
230 }
231 else
232 pthread_detach(tid); //para que thread não fique "zombie"
233 }
234 }
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
- 4 -
257
258 /*********************************************************************/
259
260 void servidor_multi_tarefa_com_threads_ugly(int s)
261 {
262 int ns, r ;
263 pthread_t tid;
264
265 while(1) {
266 ns = accept(s, NULL, NULL);
267 if(ns < 0) {
268 perror("accept");
269 continue;
270 }
271
272 r = pthread_create(&tid,
273 NULL,
274 (void *(*)(void *)) atende_pedido,
275 (void *) (long) ns);
276 if(r != 0)
277 atende_pedido(ns);
278 else
279 pthread_detach(tid);
280
281 }
282 }
283

- 5 -

Você também pode gostar