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 }