-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path22.c
172 lines (132 loc) · 4.85 KB
/
22.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <netdb.h>
#include <signal.h>
#define PORTNUM 15000
main(int argc, char **argv)
{
int s, ns;
int ppid;
int nport;
struct sockaddr_in serv_addr, clnt_addr;
struct hostent *hp;
char buf[80], hname[80];
nport = PORTNUM;
nport = htons((u_short)nport);
if((s = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror("Error in socket() call"); exit(1);
}
bzero(&serv_addr, (size_t)sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = nport;
if(bind(s, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) == -1)
{
perror(" Error in bind() call"); exit(1);
}
fprintf(stderr, "Server ready: %s\n", inet_ntoa(serv_addr.sin_addr));
/*
listen - информирует систему о том, что сервер готов принимать запросы
(т.е. просит организовать очередь для запросов к серверу)
#include
int listen(int s, int backlog);
s - дескриптор гнезда
backlog - желаемое значение длины очереди
*/
if(listen(s, 5) == -1)
{
perror("Error in listen() call"); exit(1);
}
while(1)
{
int addrlen, pid;
bzero(&clnt_addr, sizeof(clnt_addr));
addrlen = sizeof(clnt_addr);
/*
accept - извлекает первый запрос из очереди запросов на
соединение и создает для него коммуникационное гнездо
#include
int accept(int s, void *addr, int *addrlen);
s - дескриптор гнезда
addr - указатель структуры, в которую будет записан адрес клиента,
с которым устанавливается соединение
addrlen - размер адр. структуры
при успешном выполнении возвращает неотрицательное число,
которое является дескриптором установленного соединения от
принятого запроса.
-1 при ошибке (устанавливается errno)
*/
if((ns = accept(s, (struct sockaddr *)&clnt_addr, &addrlen)) == -1)
{
perror("Error in accept() call"); exit(1);
}
fprintf(stderr, "Client @ %s\n", inet_ntoa(clnt_addr.sin_addr));
// Создание дочернего процесса для организации связи с клиентом
if((pid = fork()) == -1)
{
perror("Error in fork() call"); exit(1);
}
if(!pid)
{
int nbytes;
int fout;
close(s);
/*
recv - прием сообщения от гнезда
#include
int recv(int s, void *buf, int len, int flags);
s - дскриптор гнезда
buf - указатель на буфер, в который принимается сообщение
len - размер буфера
recv(), recvfrom() возвращает:
n успешное завершение - длина принятого сообщения
0 гнездо блокировано
-1 ошибка (устанавливается errno)
*/
while((nbytes = recv(ns, buf, sizeof(buf), 0)) != 0)
{
if(!strcmp("terminate", buf))
{
pid_t ppid = getppid();
if(kill(ppid, SIGKILL) == -1)
{
perror("Shutdown request failed");
#define FAILED "Failed to shut the server down.\n"
send(ns, FAILED, strlen(FAILED) + 1, 0);
}
else
{
fprintf(stderr, "Server has been shut down...\n");
#define OK "Server has been shut down.\n"
send(ns, OK, strlen(OK) + 1, 0);
}
}
else
/*
send() - отправить сообщение
#include
int send(int s, const void *msg, int len, int flags);
s - дескриптор гнезда
msg - указатель на буфер с сообщением
len - длина сообщения
flags:
MSG_OOB - экстренные данные
send(), sendto() возвращают:
n успешное завершение, передано n байтов
-1 ошибка (устанавливается errno)
*/
send(ns, buf, sizeof(buf), 0);
}
close(ns);
exit(0);
}
close(ns);
}
}