1 #include<stdio.h>
2 #include<stdlib.h>
3 #include<string.h>
4 #include<errno.h>
5 #include<sys/types.h>
6 #include<sys/socket.h>
7 #include<unistd.h>
8
9 ////
10 #include <netinet/in.h> /* sockaddr_in{} and other Internet defns */
11 #include <arpa/inet.h> /* inet(3) functions */
12 #include <sys/epoll.h> /* epoll function */
13 #include <fcntl.h> /* nonblocking */
14 #include <sys/resource.h> /*setrlimit */
15 #include <iostream>
16 #include <string>
17 #include <thread>
18
19 #define MAXEPOLLSIZE 10000
20 // #define MAXLINE 10240
21
22 const int MAXLINE = 1024;
23
24 namespace echo {
25 class EchoServer {
26 public:
27 EchoServer() = default;
28 ~EchoServer() = default;
29
30 void Run();
31 void Wait() {
32 if (worker_.joinable()) {
33 worker_.join();
34 }
35 }
36
37 protected:
38 void Init();
39 // Thread add fd.
40 int DoAccept(struct epoll_event& ev);
41
42 // recv
43 int DoRecieve();
44
45 int DoListen();
46 int DoBind();
47 int DoSetSocket();
48 int SetNoBlock(int fd);
49 int CreateSocket();
50 int CreateEpoll();
51 void DoRun();
52 int Process(struct epoll_event& ev);
53 int DoProcess(struct epoll_event& ev);
54
55 protected:
56 int listen_fd_;
57 int cur_fds_{1};
58 int epoll_fd_;
59 short port_{6666};
60 struct epoll_event ev_;
61 struct sockaddr_in servaddr_;
62 bool exit_{false};
63 std::thread worker_;
64 };
65
66
67 void EchoServer::Init() {
68 auto ret = CreateSocket();
69 if (ret < 0) {
70 return;
71 }
72 ret = DoSetSocket();
73 if (ret < 0) {
74 return;
75 }
76 ret = DoBind();
77 if (ret < 0) {
78 return;
79 }
80 ret = DoListen();
81 if (ret < 0) {
82 return;
83 }
84 ret = CreateEpoll();
85 if (ret < 0) {
86 return;
87 }
88 }
89
90 void EchoServer::Run() {
91 Init();
92 std::thread t([this]() {
93 DoRun();
94 });
95 worker_ = std::move(t);
96 }
97
98 void EchoServer::DoRun() {
99 std::cout << "EchoServer run." << std::endl;
100 std::cout << "epoll_fd_ = " << epoll_fd_ << std::endl;
101 struct epoll_event events[MAXEPOLLSIZE];
102 while (!exit_) {
103 int nfds = epoll_wait(epoll_fd_, events, cur_fds_, -1);
104 if (-1 == nfds) {
105 std::cout << "epoll_wait error!" << std::endl;
106 continue;
107 }
108 std::cout << "nfds = " << nfds << std::endl;
109 for (size_t i = 0; i < nfds; ++i) {
110 Process(events[i]);
111 }
112 usleep(1000);
113 }
114 }
115
116 int EchoServer::Process(struct epoll_event& ev) {
117 if (ev.data.fd == listen_fd_) {
118 auto ret = DoAccept(ev);
119 if (ret < 0) return -1;
120 } else {
121 return DoProcess(ev);
122 }
123 return 0;
124 }
125
126 int EchoServer::DoProcess(struct epoll_event& ev) {
127 if (ev.events & EPOLLOUT) {
128 return 0;
129 }
130 std::cout << __func__ << std::endl;
131 int fd = ev.data.fd;
132 char buf[MAXLINE];
133 auto ret = read(fd, buf, MAXLINE);
134 // auto ret = recv(fd, buf, 3, 0);
135
136 if (ret == 0) {
137 std::cout << "client close the connection." << std::endl;
138 close(fd);
139 return -1;
140 }
141 if (ret < 0) {
142 std:: cout << "read error, fd = " << fd << ", ret=" << ret << std::endl;
143 // close(fd);
144 return -1;
145 }
146 buf[ret] = 0x0;
147 std::cout << "recv message: " << buf << std::endl;
148
149 return 0;
150 }
151
152 // Thread add fd.
153 int EchoServer::DoAccept(struct epoll_event& ev) {
154 std::cout << __func__ << std::endl;
155 struct sockaddr_in cli_addr;
156 socklen_t socklen = sizeof(struct sockaddr_in);
157 int connfd = accept(listen_fd_, (struct sockaddr *)&cli_addr, &socklen);
158 if (connfd < 0) {
159 std::cout << "accept error." << std::endl;
160 return -1;
161 }
162 std::cout << "accept from " << inet_ntoa(cli_addr.sin_addr)
163 << ":" << cli_addr.sin_port
164 << ", fd = " << connfd << std::endl;
165
166 if (cur_fds_ >= MAXEPOLLSIZE) {
167 std::cout << "too many connection, more than " << MAXEPOLLSIZE << std::endl;
168 close(connfd);
169 return -1;
170 }
171
172 if (SetNoBlock(connfd) < 0) {
173 std::cout << "set no block failed." << std::endl;
174 // return -1;
175 }
176
177 ev.events = EPOLLIN; // | EPOLLOUT;
178 ev.data.fd = connfd;
179 if (epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, connfd, &ev) < 0) {
180 std::cout << "add socket " << connfd
181 << " to epoll failed: " << strerror(errno) << std::endl;
182 close(connfd);
183 return -1;
184 }
185 cur_fds_++;
186
187 return connfd;
188 }
189
190 // recv
191 int EchoServer::DoRecieve() {
192 return 0;
193 }
194
195 int EchoServer::DoListen() {
196 if (listen(listen_fd_, 1024) == -1)
197 {
198 std::cout << "listen error" << std::endl;
199 return -1;
200 }
201 return 0;
202 }
203
204 int EchoServer::DoBind() {
205 auto ret = bind(listen_fd_, (struct sockaddr *) &servaddr_, sizeof(struct sockaddr));
206 if (ret == -1) {
207 std::cout << "bind error" << std::endl;
208 return -1;
209 }
210 return 0;
211 }
212
213 int EchoServer::DoSetSocket() {
214 int opt = 1;
215 setsockopt(listen_fd_, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
216 return 0;
217 }
218
219 int EchoServer::SetNoBlock(int fd) {
220 if (fcntl(fd, F_SETFL, fcntl(fd, F_GETFD, 0)|O_NONBLOCK) == -1) {
221 return -1;
222 }
223 return 0;
224 }
225
226 int EchoServer::CreateSocket() {
227 socklen_t socklen = sizeof(struct sockaddr_in);
228 struct rlimit rt;
229 char buf[MAXLINE];
230
231 rt.rlim_max = rt.rlim_cur = 10000; // MAXEPOLLSIZE;
232 if (setrlimit(RLIMIT_NOFILE, &rt) == -1)
233 {
234 std::cout << "setrlimit error" << std::endl;
235 return -1;
236 }
237
238
239 bzero(&servaddr_, sizeof(servaddr_));
240 servaddr_.sin_family = AF_INET;
241 servaddr_.sin_addr.s_addr = htonl (INADDR_ANY);
242 servaddr_.sin_port = htons (port_);
243
244 listen_fd_ = socket(AF_INET, SOCK_STREAM, 0);
245 if (listen_fd_== -1) {
246 std::cout << "create socket failed." << std::endl;
247 return -1;
248 }
249 return 0;
250 }
251
252 int EchoServer::CreateEpoll() {
253 epoll_fd_ = epoll_create(MAXEPOLLSIZE);
254 ev_.events = EPOLLIN | EPOLLET;
255 ev_.data.fd = listen_fd_;
256 if (epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, listen_fd_, &ev_) < 0)
257 {
258 std::cout << "epoll set error: fd=" << listen_fd_ << std::endl;
259 return -1;
260 }
261
262 return 0;
263 }
264
265 } // namespace echo
266
267 int main() {
268 echo::EchoServer server;
269 server.Run();
270 server.Wait();
271 return 0;
272 }