-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathserver.c
More file actions
137 lines (111 loc) · 4.26 KB
/
server.c
File metadata and controls
137 lines (111 loc) · 4.26 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
126
127
128
129
130
131
132
133
134
135
#include <stdio.h>
#include <arpa/inet.h>//for htonl and sockaddr_in
#include <unistd.h>//for getopt,read,write,close
#include <stdlib.h>//for atoi
#include <string.h>//for memset and memcpy
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>//for errno
#include <signal.h>//for signal func
#include "server_comm.h"
#include "threadpool.h"
#include <stdbool.h>
#define TCP_PORT 7878
#define QUEUE_SIZE 10
#define POOL_SIZE 4
void ctrl_c_signal_handler(int sig_num);
bool stop;
const int queue_size=15;
int main(int argc, char *argv[]){
int listenfd=0,connfd=0;
int tcp_port=0;
int num_threads=POOL_SIZE;
struct sockaddr_in serv_addr;
char opt;
//AF_INET connection with differnent machine
//SOCK_STREAM TCP connection
//SOCK_NONBLOCK mark socket as non blocking
//when accept is called and there is no pending connections
//accept blocks but with SOCK_NONBLOCK it returns immidiately with
//error EAGAIN or EWOULDBLOCK
if((listenfd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0))== -1)
{
printf("Error : Could not create socket\n");
printf("Errno %d\n",errno);
return -1;
}
//optstring(last argument in getopt) is a string containing the legitimate option characters.
//If such a character is followed by a colon, the option requires an
//argument, so getopt() places a pointer to the following text in the
//same argv-element, or the text of the following argv-element, in
//optarg. Two colons mean an option takes an optional arg
while ((opt = getopt (argc, argv, "p:t:")) != -1){
switch(opt){
case 'p':
tcp_port=atoi(optarg);
break;
case 't':
num_threads=atoi(optarg);
break;
case '?':
//getopt gives ? if it is unable to recoganize an option
printf("Error:wrong format\n");
printf("Usage ./server [-t tcp_port]\n");
return -1;
break;
}
}
if(tcp_port==0)
tcp_port = TCP_PORT;
memset(&serv_addr, '0', sizeof(serv_addr));
//AF_INET tell that the connection is with different machine
//AF_UNIX connect inside same machine
serv_addr.sin_family = AF_INET;
//To accept connctions from all IPs
serv_addr.sin_addr.s_addr=htonl(INADDR_ANY);
//The htonl(uint32_t hostlong) function converts the unsigned integer
//hostlong from host byte order to network byte order.
//htonl was giving wrong value htons gives correct
serv_addr.sin_port=htons(tcp_port);
if(bind(listenfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr))==-1){
printf("Error:Bindint with port # %d failed\n",tcp_port);
printf("Errno %d\n",errno);
if(errno == EADDRINUSE)
printf("Another socket is already listening on the same port\n");
return -1;
}
//The backlog(second arg of listen) argument defines the maximum length to which the queue of
//pending connections for sockfd may grow. If a connection request
//arrives when the queue is full, the client may receive an error
// with an indication of ECONNREFUSED or, if the
// underlying protocol supports retransmission,
//the request may be ignored so that a later reattempt at connection succeeds.
if(listen(listenfd, QUEUE_SIZE) == -1){
printf("Error:Failed to listen\n");
printf("Errno %d\n",errno);
if(errno == EADDRINUSE)
printf("Another socket is already listening on the same port\n");
return -1;
}
printf("Lintning on TCP port %d\n",tcp_port);
threadpool_t *tp=threadpool_create(num_threads,queue_size,0);
printf("Thread pool size %d\n",tp->thread_count);
signal(SIGINT,ctrl_c_signal_handler);
stop=false;
while(!stop){
connfd = accept(listenfd, (struct sockaddr*)NULL ,NULL); // accept awaiting request
if(connfd!=-1){
threadpool_add(tp,server_run,connfd,0);
}else{
//sleep for 0.5 seconds
usleep(500000);
}
}
close(listenfd);
threadpool_destroy(tp,0);//wait until all tasks are finished
return 0;
}
void ctrl_c_signal_handler(int sig_num){
printf("Exiting\n");
stop=true;
}