-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathserver.c
167 lines (131 loc) · 3.66 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
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/time.h>
#define TRUE 1
#define FALSE 0
#define MAX_CLIENTS 100
int CLIENTS[MAX_CLIENTS];
struct sockaddr_in ADDRESS;
void CHECK(int returnVal) {
if (returnVal < 0) {
perror("Failed!");
exit(EXIT_FAILURE);
}
}
int startServer(int port) {
int serverSocket;
ADDRESS.sin_family = AF_INET;
ADDRESS.sin_addr.s_addr = INADDR_ANY;
ADDRESS.sin_port = htons(port);
CHECK((serverSocket = socket(AF_INET , SOCK_STREAM , 0)));
int opt = 1;
//set master socket to allow multiple connections.
if(setsockopt(serverSocket, SOL_SOCKET,
SO_REUSEADDR, (char *)&opt, sizeof(opt)) < 0 )
{
perror("setsockopt");
exit(EXIT_FAILURE);
}
CHECK(bind(serverSocket, (struct sockaddr *)&ADDRESS, sizeof(ADDRESS)));
return serverSocket;
}
int handleNewConnection(int serverSocket) {
int newSocket, i, addrlen;
char *message = "Hello From Server.";
addrlen = sizeof(ADDRESS);
if ((newSocket = accept(serverSocket,
(struct sockaddr *)&ADDRESS, (socklen_t*)&addrlen))<0)
{
perror("accept");
exit(EXIT_FAILURE);
}
//inform user of socket number - used in send and receive commands
printf("New connection , socket fd is %d , ip is : %s , port : %d \
\n" , newSocket , inet_ntoa(ADDRESS.sin_addr) , ntohs(ADDRESS.sin_port));
//send new connection greeting message
if(send(newSocket, message, strlen(message), 0) != strlen(message) )
{
perror("send");
}
puts("Welcome message sent successfully");
//add new socket to array of sockets
for (i = 0; i < MAX_CLIENTS; i++)
{
//if position is empty
if(CLIENTS[i] == 0)
{
CLIENTS[i] = newSocket;
printf("Adding to list of sockets as %d\n" , i);
break;
}
}
return 1;
}
int handleClientActivity(int clientSd, int clientSdIndex) {
int valread, addrlen;
char buffer[1025];
addrlen = sizeof(ADDRESS);
if ((valread = read(clientSd, buffer, 1024)) == -1) {
printf("Closing client %d\n", clientSd);
close(clientSd);
CLIENTS[clientSdIndex] = 0;
} else {
printf("sending message to client.....\n");
buffer[valread] = '\0';
send(clientSd, buffer, strlen(buffer), 0);
}
return 1;
}
int listenForConnection(int serverSocket) {
CHECK(listen(serverSocket, MAX_CLIENTS));
fd_set readfds;
int maxSd, sd, i, activity;
while(TRUE) {
FD_ZERO(&readfds);
//add master socket to set
FD_SET(serverSocket, &readfds);
maxSd = serverSocket;
//add child sockets to set
for ( i = 0; i < MAX_CLIENTS ; i++) {
//socket descriptor
sd = CLIENTS[i];
//if valid socket descriptor then add to read list
if(sd > 0) {
FD_SET( sd , &readfds);
}
//highest file descriptor number, need it for the select function
if(sd > maxSd) {
maxSd = sd;
}
}
activity = select(maxSd + 1 , &readfds , NULL , NULL , NULL);
if ((activity < 0) && (errno!=EINTR)) {
printf("select error");
}
if (FD_ISSET(serverSocket, &readfds)) {
handleNewConnection(serverSocket);
}
//else its some IO operation on some other socket
for (i = 0; i < MAX_CLIENTS; i++) {
sd = CLIENTS[i];
if (FD_ISSET(sd , &readfds)) {
handleClientActivity(sd, i);
}
}
}
return 1;
}
int main(int argc , char *argv[])
{
int masterSocket;
CHECK((masterSocket = startServer(atoi(argv[1]))));
CHECK(listenForConnection(masterSocket));
return 1;
}