tcp echo_server

  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 }
原文地址:https://www.cnblogs.com/guoliushui/p/13441896.html