-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathserver.c
More file actions
125 lines (125 loc) · 3.06 KB
/
Copy pathserver.c
File metadata and controls
125 lines (125 loc) · 3.06 KB
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
#include<limits.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<stdbool.h>
#include<netinet/in.h>
#include<pthread.h>
#include"myqueue.h"
#define SERVERPORT 9082
#define BUFSIZE 4096
#define SOCKETERROR (-1)
#define SERVER_BACKLOG 1
#define THREAD_POOL_SIZE 20
pthread_t thread_pool[THREAD_POOL_SIZE];
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t condition_var = PTHREAD_COND_INITIALIZER; //Condition
variable initializer
typedef struct sockaddr_in SA_IN;
typedef struct sockaddr SA;
void handle_connection(int client_socket);
int check(int exp,const char *msg);
void *thread_function(void *arg);
int main(int argc , char **argv)
{
int server_socket,client_socket,addr_size;
SA_IN server_addr , client_addr;
for(int i = 0;i<THREAD_POOL_SIZE;i++) //creating threads
binded to the thread_function
{
pthread_create(&thread_pool[i],NULL,thread_function,NULL);
}
check((server_socket = socket(AF_INET,SOCK_STREAM,0)),"Failed to
create a socket");
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(SERVERPORT);
check(bind(server_socket,(SA*)&server_addr,sizeof(server_addr)),"Bind
Failed");
check(listen(server_socket,SERVER_BACKLOG),"Listen Failed!");
while(true)
{
printf("Waiting for connections...\n");
addr_size = sizeof(SA_IN);
check(client_socket =
accept(server_socket,(SA*)&client_addr,(socklen_t*)&addr_size),"accept
failed");
printf("Connected!\n");
int *pclient = malloc(sizeof(int));
*pclient = client_socket;
pthread_mutex_lock(&mutex);
enqueue(pclient);
pthread_cond_signal(&condition_var);
pthread_mutex_unlock(&mutex);
}
}
int check(int exp, const char *msg)
{
if(exp== SOCKETERROR)
{
perror(msg);
exit(1);
}
return exp;
}
void *thread_function(void *arg)
{
while(true)
{
int *pclient;
pthread_mutex_lock(&mutex); //racecondition fix
if((dequeue())==NULL)
{
pthread_cond_wait(&condition_var,&mutex); //we passed mutex
here because if a thread suspends it releases the lock and it will alow
some other thread to grab it and we dont want that so we passed in the
mutex too make it locked
pclient = dequeue();
}
pthread_mutex_unlock(&mutex);
if(pclient!=NULL)
{
handle_connection(*pclient);
free(pclient);
}
// else{
// sleep(1); //not a good solution for high cpu usage
// }
}
}
void handle_connection(int client_socket)
{
char buffer[BUFSIZE];
size_t bytes_read;
char actualpath[_PC_PATH_MAX+1];
// reading the client request
bytes_read = read(client_socket, buffer, sizeof(buffer) - 1);
check(bytes_read, "recv error");
buffer[bytes_read - 1] = '\0';
printf("REQUEST: %s\n", buffer);
fflush(stdout);
if (realpath(buffer, actualpath) == NULL)
{
printf("ERROR(badpath): %s\n", buffer);
close(client_socket);
return;
}
FILE *fp = fopen(actualpath, "r");
if (fp == NULL)
{
printf("ERROR(open): %s\n", buffer);
close(client_socket);
return;
}
while ((bytes_read = fread(buffer, 1, sizeof(buffer), fp)) > 0)
{
printf("sending %zu bytes\n", bytes_read);
write(client_socket, buffer, bytes_read);
}
close(client_socket);
fclose(fp);
printf("closing connection\n");
}