• 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 }
  • 相关阅读:
    PHP连接MySQL报错:SQLSTATE[HY000] [2002] Can't connect to local MySQL server through socket 'MySQL' (2)
    Nginx 开启PATHINFO支持ThinkPHP框架实例
    《征服 C 指针》笔记6:练习——挑战那些复杂的声明
    《征服 C 指针》摘录4:函数 与 指针
    《征服 C 指针》摘录5:函数形参 和 空的下标运算符[]
    《征服 C 指针》摘录3:数组 与 指针
    《征服 C 指针》摘录2:C变量的 作用域 和 生命周期(存储期)
    《征服 C 指针》摘录1:什么是空指针?区分 NULL、0 和 ''
    自定义 array_map() 对应的递归函数 array_map_recursive()
    【C语言入门教程】7.5 枚举
  • 原文地址:https://www.cnblogs.com/guoliushui/p/13441896.html
Copyright © 2020-2023  润新知