-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathServer.c
157 lines (117 loc) · 3.72 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
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#define SERV_TCP_PORT 23 /* server's port number */
#define MSG_LEN 2048
#define MAX_CLIENT 512
//initialize global variables
int clientCount = 0; //counter for the connected clients
int clientSocks[MAX_CLIENT]; //array for the connected clients
pthread_mutex_t mutex; // declare mutex variable
//show message all connected clients
void msgAll(char *msg, int len)
{
int i;
pthread_mutex_lock(&mutex); //enter the critical section
//send message all connected clients
for (i = 0; i < clientCount; i++)
write(clientSocks[i], msg, len);
pthread_mutex_unlock(&mutex); //leave the critical section
}
//receive client's message and display it to all connected clients
void* serverClient(void *arg)
{
int clientSock = *((int*)arg);
int str_len = 0;
int i;
char msg[MSG_LEN];
//loop until client terminates
while ((str_len = read(clientSock, msg, sizeof(msg))) != 0)
msgAll(msg, str_len);
pthread_mutex_lock(&mutex); //enter the critical section
//removes client from list before terminating thread
for (i = 0; i < clientCount; i++)
{
if (clientSock == clientSocks[i])
{
while (i < clientCount - 1)
{
clientSocks[i] = clientSocks[i + 1];
i++;
}
break;
}
}
clientCount--;
pthread_mutex_unlock(&mutex); //leave the critical section
//close connection
close(clientSock);
return NULL;
}
int main(int argc, char *argv[])
{
int serveSock, clientSock; //server and client sockets
struct sockaddr_in serv_addr, cli_addr; //socket addresses
int cli_addr_sz; //size of the client cli_addr
int port;
pthread_t thread; //initialize thread
/* command line: server [port_number] */
if (argc == 2)
{
sscanf(argv[1], "%d", &port); /* read the port number if provided */
}
else
{
port = SERV_TCP_PORT;
}
pthread_mutex_init(&mutex, NULL);
//open a TCP socket
if((serveSock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("can't open stream socket");
exit(1);
}
//bind the local address, so that the client can send to server
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(port);
// bind server's address information to the server socket
if (bind(serveSock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0)
{
perror("can't bind local address");
exit(1);
}
//listen to the socket
if (listen(serveSock, 5) == -1)
perror("listen failed");
//welcome message
printf("Server running \n");
while (1)
{
//wait for a connection from a client
cli_addr_sz = sizeof(cli_addr);
clientSock = accept(serveSock, (struct sockaddr*)&cli_addr, &cli_addr_sz);
if (clientSock < 0)
{
perror("can't accept local connection");
}
//add new clients to the list
pthread_mutex_lock(&mutex); //enter critical section
clientSocks[clientCount++] = clientSock;
pthread_mutex_unlock(&mutex); //leave critical section
//make a thread to serve client
pthread_create(&thread, NULL, serverClient, (void*)&clientSock);
//detach from main thread
pthread_detach(thread);
//print connected client's IP address
printf("User joined \n");
}
close(serveSock);
return 0;
}