-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathserver.c
333 lines (293 loc) · 10.8 KB
/
server.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
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/time.h>
#include <sys/select.h>
#include <time.h>
#include <curses.h>
#define BUF_SIZE 1024
int game = 1;
void error_handling(char * buf); // Error Handling
int newCard(); // 카드 랜덤 배분
int serv_sock, clnt_sock;
struct sockaddr_in serv_adr, clnt_adr; // 서버를 위한 소켓 : Serv_adr, 클라이언트를 위핸 소켓 clnt_adr
fd_set reads, cpy_reads; // fd_set들
int count_cli = 0; // 클라이언트 갯수체크
int counting=0;
socklen_t adr_sz; // socklenth 변수
int fd_max, str_len, fd_num, i;
char buf[BUF_SIZE];
char buf2[BUF_SIZE*10];
int main(int argc, char * argv[]){
struct timeval timeout; // select를 사용하기 위한 timeval 구조체. Non-Blocking구현을 위해 각 FD들이 wait할 시간을 설정해줌
if(argc!=2){
printf("Usage: %s<port>\n",argv[0]);
exit(1);
}
serv_sock = socket(PF_INET, SOCK_STREAM, 0); // server 소켓
memset(&serv_adr, 0, sizeof(serv_adr)); // 소켓 초기화
// 서버 설정. IPv4, 접속가능 주소는 아무거나, 포트는 받아 오는 걸로.
serv_adr.sin_family = AF_INET;
serv_adr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_adr.sin_port = htons(atoi(argv[1]));
// 바인드 및 리슨
if(bind(serv_sock, (struct sockaddr *)&serv_adr, sizeof(serv_adr)) == -1)
error_handling("bind() error!");
if(listen(serv_sock, 5) == -1)
error_handling("listen() error");
// fd_set을 초기화함
FD_ZERO(&reads);
// serv_sock의 번호에 해당하는 set을 초기화하여줌. 서버 소켓 번호 3
FD_SET(serv_sock, &reads);
fd_max = serv_sock; // fd_set에서 0 : stdin , 1 : stdout, 2 : stderr , 3: 추가된 서버 소켓번호 , 그럼으로 for를 돌리기위한 fd_max는 서버 소켓 번호.
while(1){
cpy_reads = reads;
// 약 5초 정도로 설정
timeout.tv_sec = 5;
timeout.tv_usec = 5000;
// 이곳에서 블락을 처리해줌 select()함수는 fd_set의 파일 디스크립터들 중에 입출력을 수행할 준비가 되거나 timeout변수에서 정해진 시간이 경과할 때까지만 블록.
// select의 리턴값은 변화가 생긴 파일 디스크립터 번호가 됨.
if((fd_num = select(fd_max + 1, &cpy_reads, 0, 0, &timeout)) == -1)
break;
if(fd_num == 0)
continue;
// 지속적으로 for문을 돌려 각 파일디스크립터들이 서버이냐 클라이언트 이냐에 따라 다르게 수행함.
for(i = 0; i < fd_max+1; i++){
// i 번째 fd가 설정이 되어있느냐 ?
if(FD_ISSET(i, &cpy_reads)){
// i 번째 스크립트가 서버 소켓의 fd이냐
if(i == serv_sock){
adr_sz = sizeof(clnt_adr);
// 지속적인 연결 수행함.
clnt_sock = accept(serv_sock, (struct sockaddr *)&clnt_adr, &adr_sz);
FD_SET(clnt_sock, &reads);
// 만약 새로 연결되었다면 fd_max를 늘려 새로운 소켓도 다음에 listen하도록 수행.
if(fd_max < clnt_sock)
fd_max = clnt_sock;
printf("connected client: %d\n", clnt_sock);
count_cli++;
counting++;
// 새로 연결이 수행되면 간단한 안내를 클라이언트에게 보냄
// 중요한점 : 코딩의 용의성을 위해 한 소켓에 read or write를 수행할때 한번에 보내는 것을 매우 추천함. 여러번 나누어 보내다보면
// 원하는 대로 수행이 안될 수도 있음. 예 ) 여러번 나누어 write를 수행하던 도중 클라이언트에서 블락을 해버림.
sprintf(buf, "Server : Welcome~\nServer : The number of clients is %d now.",counting);
write(clnt_sock, buf, sizeof(buf));
// 현제 존재하는 클라이언트들에게 새로운 클라이언트가 들어옴을 알림.
for(int k = 4; k < 4+count_cli; k++)
{
if(k != clnt_sock){
sprintf(buf,"client %d has joined this game room\n",clnt_sock);
write(k, buf,sizeof(buf));
}
}
// i 번째 fd가 클라이언트 관련 소켓이면
}else {
// 정해준 시간만큼 읽음 대기.
//str_len = read(i, buf, BUF_SIZE);
// 읽어 들였는데 0이다. 이는 클라이언트 소켓이 닫혔음을 의미함.
if(str_len == 0){
for(int k = 4; k < 4+count_cli; k++)
{
// 각 클라이언트들에게 해당 클라이언트가 나갔음을 공지함.
if(k != i){
sprintf(buf,"client %d has left this game room\n",i);
write(k, buf,sizeof(buf));
}
}
// 해당번호의 fd를 비워줌.
FD_CLR(i, &reads);
close(i);
printf("closed client: %d \n", i);
//count_cli--;
counting--;
}else{
while (game){
int chip1 = 20;
int chip2 = 20;
sprintf(buf2, "player1가 베팅할 칩 개수를 입력해주세요.\n");
write(4, buf2, strlen(buf2));
sprintf(buf2, "player1의 베팅을 기다리고 있습니다.\n");
write(5, buf2, BUF_SIZE);
read(4, buf, BUF_SIZE);
sprintf(buf2, "player1: %s\n", buf);
write(5, buf2, BUF_SIZE);
sprintf(buf2, "player2가 베팅할 칩 개수를 입력해주세요.\n");
write(5, buf2, BUF_SIZE);
sprintf(buf2, "player2의 베팅을 기다리고 있습니다.\n");
write(4, buf2, BUF_SIZE);
read(5, buf, BUF_SIZE);
sprintf(buf2, "player2: %s\n", buf);
write(4, buf2, BUF_SIZE);
if (chip1*chip2 == 0){ //chip1또는 chip2가 0이 되면 종료
game = 0;
}
}
}
}
}
}
}
close(serv_sock);
return 0;
}
void error_handling(char * buf){
fputs(buf, stderr);
fputc('\n', stderr);
exit(1);
}
void printmsg(int num){
int temp = strlen(buf2);
//strncat(buf2, buf, str_len);
write(num, buf2, temp);
}
int newCard()
{
srand(time(NULL));
int random = 0; // 정수형 변수 선언
random = rand() % 9 + 1; // 난수 생성
if (random == 1)
{
printf("***********\n");
printf("* *\n");
printf("* * *\n");
printf("* * * *\n");
printf("* * *\n");
printf("* * *\n");
printf("* * *\n");
printf("* * *\n");
printf("* ***** *\n");
printf("* *\n");
printf("***********\n");
}
else if (random == 2)
{
printf("***********\n");
printf("* *\n");
printf("* *** *\n");
printf("* * * *\n");
printf("* * *\n");
printf("* * *\n");
printf("* * *\n");
printf("* * *\n");
printf("* ***** *\n");
printf("* *\n");
printf("***********\n");
}
else if (random == 3)
{
printf("***********\n");
printf("* *\n");
printf("* *** *\n");
printf("* * * *\n");
printf("* * *\n");
printf("* ** *\n");
printf("* * *\n");
printf("* * * *\n");
printf("* *** *\n");
printf("* *\n");
printf("***********\n");
}
else if (random == 4)
{
printf("***********\n");
printf("* *\n");
printf("* * *\n");
printf("* ** *\n");
printf("* * * *\n");
printf("* * * *\n");
printf("* ******* *\n");
printf("* * *\n");
printf("* * *\n");
printf("* *\n");
printf("***********\n");
}
else if (random == 5)
{
printf("***********\n");
printf("* *\n");
printf("* ***** *\n");
printf("* * *\n");
printf("* **** *\n");
printf("* * *\n");
printf("* * *\n");
printf("* * * *\n");
printf("* *** *\n");
printf("* *\n");
printf("***********\n");
}
else if (random == 6)
{
printf("***********\n");
printf("* *\n");
printf("* *** *\n");
printf("* * * *\n");
printf("* * *\n");
printf("* **** *\n");
printf("* * * *\n");
printf("* * * *\n");
printf("* *** *\n");
printf("* *\n");
printf("***********\n");
}
else if (random == 7)
{
printf("***********\n");
printf("* *\n");
printf("* ***** *\n");
printf("* * * *\n");
printf("* * * *\n");
printf("* * *\n");
printf("* * *\n");
printf("* * *\n");
printf("* * *\n");
printf("* *\n");
printf("***********\n");
}
else if (random == 8)
{
printf("***********\n");
printf("* *\n");
printf("* *** *\n");
printf("* * * *\n");
printf("* * * *\n");
printf("* *** *\n");
printf("* * * *\n");
printf("* * * *\n");
printf("* *** *\n");
printf("* *\n");
printf("***********\n");
}
else if (random == 9)
{
printf("***********\n");
printf("* *\n");
printf("* *** *\n");
printf("* * * *\n");
printf("* * * *\n");
printf("* **** *\n");
printf("* * *\n");
printf("* * * *\n");
printf("* *** *\n");
printf("* *\n");
printf("***********\n");
}
else if (random == 10)
{
printf("***********\n");
printf("* *\n");
printf("* * ** *\n");
printf("* * * * *\n");
printf("* * * * *\n");
printf("* * * * *\n");
printf("* * * * *\n");
printf("* * * * *\n");
printf("* * ** *\n");
printf("* *\n");
printf("***********\n");
}
return random;
}