-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathserver_kqueue.cpp
98 lines (94 loc) · 2.85 KB
/
server_kqueue.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
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/event.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <errno.h>
#include <vector>
#include <thread>
int kq = kqueue();
int MAX_CONN = 1000;
void callback() {
struct kevent evList[MAX_CONN];
std::vector<char> buf(256);
while (true) {
int nev = kevent(kq, NULL, 0, evList, MAX_CONN, NULL);
if (nev == -1) {
if (errno == EINTR) // interrupted, try again
continue;
perror("kevent()");
return;
}
for (int i = 0; i < nev; i++) {
if (evList[i].filter != EVFILT_READ)
continue;
int connect = static_cast<int>(evList[i].ident);
while (true) {
int ret = recv(connect, buf.data(), buf.capacity(), 0);
if (ret <= 0) {
if (ret == -1 && errno == EINTR) // interrupted, try again
continue;
if (ret == -1)
perror("recv()");
printf("client %d disconnected\n", connect);
close(connect); // close will also remove associated event
break;
}
int size = ret;
char *ptr = buf.data();
while (size > 0 && (ret = send(connect, ptr, size, 0)) != 0) {
if (ret == -1) {
if (errno == EINTR)
continue;
perror("send()");
break;
}
size -= ret;
ptr += ret;
}
break;
}
}
}
}
int main() {
int server = socket(AF_INET, SOCK_STREAM, 0);
if (server == -1) {
perror("socket()");
exit(EXIT_FAILURE);
}
struct sockaddr_in srv_addr, clnt_addr;
uint32_t addr_size = sizeof(srv_addr);
srv_addr.sin_family = AF_INET;
srv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
srv_addr.sin_port = htons(1234);
struct kevent evSet;
if (bind(server, (struct sockaddr*) &srv_addr, addr_size) != 0) {
perror("bind()");
exit(EXIT_FAILURE);
}
if (listen(server, MAX_CONN) != 0) {
perror("listen()");
exit(EXIT_FAILURE);
}
bool run = false;
while (true) {
int connect = accept(server, (struct sockaddr*) &clnt_addr, &addr_size);
if (connect < 0) {
perror("accept()");
exit(EXIT_FAILURE);
}
EV_SET(&evSet, connect, EVFILT_READ, EV_ADD, 0, 0, NULL);
kevent(kq, &evSet, 1, NULL, 0, NULL);
if (!run) {
run = true;
std::thread t(callback);
t.detach();
}
}
return 0;
}