/
server.cpp
144 lines (119 loc) · 3.19 KB
/
server.cpp
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
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <arpa/inet.h>
#include <vector>
#include <unistd.h>
#include <stdlib.h>
#include <cstring>
#include <string>
#include <iostream>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <signal.h>
#include <list>
#include <netdb.h>
#include <ev.h>
#define BUFSIZE 1024
//CREATING A LIST OF CLIENTS
std::list<int> clients;
class my_io: public ev_io
{
public:
int val;
};
int set_nonblock(int fd)
{
int flags;
#ifdef O_NONBLOCK
if (-1 == (flags = fcntl(fd, F_GETFL, 0))) flags = 0;
return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
#endif
flags = 1;
return ioctl(fd, FIONBIO, &flags);
}
//CALLBACK ON CLIENT MESSAGE / DISCONNECT
static void read_cb(struct ev_loop *loop, struct ev_io *client, int revents)
{
char cache[BUFSIZE];
char *buf = (char *) malloc(BUFSIZE);
int buf_len = BUFSIZE;
if (0 == recv(client->fd, cache, BUFSIZE, 0))
//CLIENT DISCONNECTED
{
clients.remove(client->fd);
std::cout << "connection terminated\n";
ev_io_stop(loop, client);
delete static_cast<my_io *>(client);
close(client->fd);
}
else
//RECIEVED MESSAGE FROM CLIENT
{
memcpy(buf, cache, BUFSIZE);
//reading whole message in buf
while (recv(client->fd, cache, BUFSIZE, 0) > 0)
{
buf_len += BUFSIZE;
buf = (char *) realloc(buf, buf_len);
memcpy(buf + (buf_len - BUFSIZE), cache, BUFSIZE);
}
std::cout << buf << std::endl;
send(client->fd, buf, BUFSIZE, 0);
}
free(buf);
}
//CALLBACK ON CLIENT ACCEPT
static void accept_cb(struct ev_loop *loop, struct ev_io *server, int revents)
{
int client_socket = accept(server->fd, 0, 0);
set_nonblock(client_socket);
clients.push_front(client_socket);
struct ev_io *watcher = new my_io;
ev_init(watcher, read_cb);
ev_io_set(watcher, client_socket, EV_READ);
ev_io_start(loop, watcher);
std::cout << "accepted connection\n";
}
int main(int argc, char **argv)
{
char *host, *port;
int c;
if (argc != 2)
throw "Not enough arguments";
//CREATING SERVER
int server = socket(AF_INET, SOCK_STREAM, 0);
//FILLING SERVER ADDRESS STRUCTURE
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(atoi(argv[1]));
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
//BINDING SERVER TO ADDRESS
if (bind(server, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0)
{
std::cerr << "Error in bind\n";
exit(1);
}
//PREPAIRING TO ACCEPT CLIENTS
if (listen(server, SOMAXCONN) < 0)
{
std::cerr << "Error in listen\n";
exit(1);
}
//MAKING EVENT LOOP
struct ev_loop *loop = ev_default_loop(0);
//MAKING EVENT FOR ACCEPT
struct ev_io *watcher = new my_io;
ev_init(watcher, accept_cb);
ev_io_set(watcher, server, EV_READ);
ev_io_start(loop, watcher);
printf("Waiting for clients...\n");
//RUNNING EVENT LOOP
while (true)
{
ev_loop(loop, 0);
}
shutdown(server, SHUT_RDWR);
close(server);
}