-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathserver.c
137 lines (114 loc) · 4.09 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
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <errno.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/select.h>
#define DEFAULT_SERVER_PORT 5432
#define MAX_MSG_SIZE 1024
#define MAX_CLIENTS 100
void exit_client(int fd, fd_set *readset, int fd_array[], int *num_clients);
int main(int argc, char *argv[])
{
int port = DEFAULT_SERVER_PORT;
int server_sockfd, client_sockfd;
struct sockaddr_in server_addr, client_addr;
int addrlen = sizeof(struct sockaddr_in);
char message[MAX_MSG_SIZE + 1],
kbd_input[MAX_MSG_SIZE + 1];
fd_set readset, tempset;
int num_clients = 0;
int fd_array[MAX_CLIENTS];
int fd;
//parse command line arguments
if(argc == 3){
if(!strcmp("-p", argv[1]))
sscanf(argv[1], "%d", &port);
else{
printf("Usage: %s [-p PORT]\n", argv[0]);
exit(0);
}
}else if(argc != 1){
printf("Usage: %s [-p PORT]\n", argv[0]);
exit(0);
}
printf("*** Server waiting ***\n");
bzero(&server_addr, addrlen);
server_sockfd = socket(AF_INET, SOCK_STREAM, 0);
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(port);
server_addr.sin_addr.s_addr = htons(INADDR_ANY);
//bind
bind(server_sockfd, (struct sockaddr *) &server_addr, addrlen);
//listen
listen(server_sockfd, 10);
FD_ZERO(&readset);
FD_SET(server_sockfd, &readset);
FD_SET(fileno(stdin), &readset);
//wait for clients
printf(">> ");
while(1){
tempset = readset;
select(FD_SETSIZE, &tempset, NULL, NULL, NULL);
for(fd = 0; fd < FD_SETSIZE; fd++){
if(FD_ISSET(fd, &tempset)){
if(fd == server_sockfd){
// accept new client connection request
client_sockfd = accept(server_sockfd, (struct sockaddr *) &client_addr, (socklen_t *)&addrlen);
if(num_clients < MAX_CLIENTS){
FD_SET(client_sockfd, &readset);
fd_array[num_clients] = client_sockfd;
//welcome client
sprintf(message, "mWelcome client %d\n", num_clients);
write(client_sockfd, message, strlen(message));
++num_clients;
fflush(stdout);
}else{
sprintf(message, "mSorry, too many clients connected. Try again later.\n");
write(client_sockfd, message, strlen(message));
close(client_sockfd);
}
}else if(fd == fileno(stdin)){
printf(">> ");
fgets(kbd_input, MAX_MSG_SIZE, stdin);
if(!strcmp("quit\n", kbd_input)){
sprintf(message, "XServer shutting down!\n");
for(fd = 0; fd < num_clients; fd++){
write(fd_array[fd], message, strlen(message));
close(fd_array[fd]);
}
close(server_sockfd);
exit(0);
}else{
for(fd = 0; fd < num_clients; fd++){
sprintf(message, "c%s", kbd_input);
write(fd_array[fd], message, strlen(message));
}
}
}else if(fd){//client socket
//client will only send EOF
//so remove that client from fd_array
exit_client(fd, &readset, fd_array, &num_clients);
}
}
}
}
return 0;
}
void exit_client(int fd, fd_set *readset, int fd_array[], int *num_clients)
{
close(fd);
FD_CLR(fd, readset);
int i;
for(i = 0; i < (*num_clients) - 1; i++)
if(fd_array[i] == fd)
break;
for(; i < (*num_clients) - 1; i++)
fd_array[i] = fd_array[i + 1];
(*num_clients)--;
}