forked from operasfantom/os-net-multiplexing
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathserver.cpp
More file actions
104 lines (88 loc) · 2.92 KB
/
Copy pathserver.cpp
File metadata and controls
104 lines (88 loc) · 2.92 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
#include <iostream>
#include <vector>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/epoll.h>
#include <unistd.h>
#include <cstring>
#include <cstdio>
#include <fcntl.h>
#include "utils.h"
using std::cout;
using std::stoi;
using std::cerr;
using std::string;
using std::vector;
void get_args(char *argv[], string &host, int &port) {
try {
port = stoi(argv[2]);
} catch (...) {
cerr << "Invalid port";
exit(EXIT_FAILURE);
}
host = argv[1];
}
void transform_msg(vector<char>& msg) {
if (msg.empty())
return;
msg[0] = 'Z';
msg.back() = '\0';
}
const int CONNECTIONS_TOTAL = 64;
const int BUFFER_SIZE = 42;
int main(int argc, char *argv[]) {
if (argc < 3) {
cout << "Usage: ./os-net-multiplexing-server [host] [port]";
exit(EXIT_FAILURE);
}
int port;
string host;
get_args(argv, host, port);
//creating socket file descriptor
int fd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0);
utils::check(fd, "in socket");
//initializing server
struct sockaddr_in server{}, client{};
server.sin_family = AF_INET;
server.sin_port = htons(port);
socklen_t s_len = sizeof(sockaddr_in);
vector<char> buffer(BUFFER_SIZE);
utils::check(inet_pton(AF_INET, host.data(), &server.sin_addr), "in inet_pton");
utils::check(bind(fd, (sockaddr *) (&server), s_len), "in bind");
utils::check(listen(fd, SOMAXCONN), "in listen");
//let's create epoll descriptor
struct epoll_event ee{}, epollout_event{}, events[CONNECTIONS_TOTAL];
int ed = epoll_create1(0);
int descriptors;
utils::add_epoll(ed, fd, &ee, EPOLLIN, EPOLL_CTL_ADD);
//running...
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wmissing-noreturn"
cout << "Running on port " << port << std::endl;
while (true) {
descriptors = epoll_wait(ed, events, CONNECTIONS_TOTAL, -1);
utils::check(descriptors, "in epoll_wait", true);
for (int i = 0; i < descriptors; i++) {
int e_fd = events[i].data.fd;
if (e_fd == fd) {
epoll_event ee_1{};
utils::handle_new_connection(fd, ed, &ee_1);
} else {
if (events[i].events & EPOLLIN) {
utils::receive_msg(&buffer[0], BUFFER_SIZE, e_fd);
utils::print_msg(buffer);
transform_msg(buffer);
struct epoll_event ee_1{};
utils::add_epoll(ed, e_fd, &ee_1, EPOLLOUT, EPOLL_CTL_MOD);
}
if (events[i].events & EPOLLOUT) {
utils::send_msg(&buffer[0], BUFFER_SIZE, e_fd);
utils::check(shutdown(e_fd, SHUT_RDWR), "in client descriptor shutdown", true);
utils::check(close(e_fd), "in client descriptor close", true);
}
}
}
}
#pragma clang diagnostic pop
}