-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.cpp
More file actions
148 lines (131 loc) · 4.65 KB
/
Copy pathmain.cpp
File metadata and controls
148 lines (131 loc) · 4.65 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
136
137
138
139
140
141
142
143
144
145
146
147
148
//
// Created by qwskyz on 2022/3/17.
//
#include <iostream>
#include <libgen.h>
#include <cstdlib>
#include <unistd.h>
#include <cerrno>
#include <csignal>
#include <cstring>
#include <cassert>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/epoll.h>
#include "threadpool.h"
#include "http_conn.h"
#include "util.h"
#define MAX_FD 65535 // max number of file description
#define MAX_EVENT_NUMBER 10000 // max number of listening events
void addSig(int sig, void (handler)(int));
int main(int argc, char *argv[]) {
// 1 handle argv
if (argc <= 1) {
std::cout << "Please run as: " << basename(argv[0]) << " {port_number}" << std::endl;
exit(-1);
}
int port = atoi(argv[1]);
// 2 add signal action
// 为了避免进程退出, 可以捕获SIGPIPE信号, 或者忽略它, 给它设置SIG_IGN信号处理函数
addSig(SIGPIPE, SIG_IGN);
// 3 create threadPool
threadPool<http_conn> *thread_pool = nullptr;
try {
thread_pool = new threadPool<http_conn>;
} catch (...) {
std::cout << "create threadPoll failed" << std::endl;
return 1;
}
http_conn *users = new http_conn[MAX_FD];
// 4 create listen socket and set reuse port
int listen_fd = socket(AF_INET, SOCK_STREAM, 0);
if (listen_fd == -1) {
perror("socket");
exit(-1);
}
int reuse = 1;
setsockopt(listen_fd, SOL_SOCKET, SO_REUSEPORT, &reuse, sizeof(reuse));
// 5 bind and listen port
struct sockaddr_in server_address{};
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = INADDR_ANY;
server_address.sin_port = htons(port);
int ret;
ret = bind(listen_fd, (struct sockaddr *) &server_address, sizeof(server_address));
if (ret == -1) {
perror("bind");
exit(-1);
}
ret = listen(listen_fd, 5);
if (ret == -1) {
perror("listen");
exit(-1);
}
// 6 create epoll fd and event array
epoll_event events[MAX_EVENT_NUMBER];
int epoll_fd = epoll_create(5);
addFd(epoll_fd, listen_fd, false);
// core all the http connect fd use the same epoll_fd
http_conn::m_epoll_fd = epoll_fd;
while (true) {
int num = epoll_wait(epoll_fd, events, MAX_EVENT_NUMBER, -1);
if (num < 0 && errno != EINTR) {
perror("epoll_wait");
break;
}
for (int i = 0; i < num; i++) {
int sock_fd = events[i].data.fd;
if (sock_fd == listen_fd) {
// it means the client has connected
struct sockaddr_in client_address{};
socklen_t client_address_length = sizeof(client_address);
// 7.1 accept the client connect
int conn_fd = accept(listen_fd, (struct sockaddr *) &client_address, &client_address_length);
if (conn_fd < 0) {
perror("accept");
continue;
}
// core check the total connected socket fd
if (http_conn::m_user_count > MAX_FD) {
// TODO send a message to client
close(conn_fd);
continue;
}
// core create a new http_conn
users[conn_fd].init(conn_fd, client_address);
// EPOLLHUP:表示对应的文件描述符被挂断
// EPOLLERR:表示对应的文件描述符发生错误
// 2.6.17 版本内核中增加了 EPOLLRDHUP 事件,代表对端断开连接
} else if (events[i].events & (EPOLLRDHUP | EPOLLHUP | EPOLLERR)) {
// 7.2 handle the accept socket
// core remember to close the fd
users[sock_fd].close_conn();
} else if (events[i].events & EPOLLIN) {
// read all data in one time
if (users[sock_fd].read()) {
// core users is the name of array, and users point to the first element of array
thread_pool->append(users + sock_fd);
} else {
users[sock_fd].close_conn();
}
} else if (events[i].events & EPOLLOUT) {
// write all data in one time
if (!users[sock_fd].write()) {
users[sock_fd].close_conn();
}
}
}
}
close(epoll_fd);
close(listen_fd);
delete[] users;
delete thread_pool;
return 0;
}
void addSig(int sig, void (handler)(int)) {
struct sigaction sa{};
memset(&sa, '\0', sizeof(sa));
sa.sa_handler = handler;
sigfillset(&sa.sa_mask);
assert(sigaction(sig, &sa, nullptr) != -1);
}