title: C++ socket multi client connect
body: <p>I write a Server which uses epoll in Linux, and I want to test how many connect it can accept in real environment. So I write a client  in Windows, the client create many sockets to connect the remote server. So there is the question, after the server accept about 1700 connections, the new socket that client create fail to connect the server and the error code is 10060. I copy the client to another Windows and run client at 2 PC at the same time, and both of them get the same result. So, the server can accept 3400 connections about. The problems may take place In windows, and I tied to fix it：</p>
  <blockquote>
  <p>[HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\Tcpip\Parameters]</p>
  <p>MaxUserPort = 65534 (Decimal)</p>
  <p>MaxHashTableSize = 65536 (Decimal)</p>
  <p>MaxFreeTcbs = 16000 (Decimal)</p>
  </blockquote>
  <p>But it doesn't help。
  There is my Server code:</p>
  <pre><code>bool GateServer::Init(std::string &amp;port)
  {
      printf(&quot;Init to port %s\n&quot;, port.c_str());
  
      m_nConnNum = 0;
  
      m_socketfd = CreateAndBindSocket(port);
  
      if (m_socketfd == -1)
      {
          abort();
      }
  
      int result = MakeSocketNonblocking(m_socketfd);
  
      if (result == -1)
      {
          abort();
      }
  
  
      int z;
      int sndbuf = 0;        /* Send buffer size */
      int rcvbuf = 0;        /* Receive buffer size */
      socklen_t optlen;        /* Option length */
  
  
      /*
      * Get socket option SO_SNDBUF:
      */
      optlen = sizeof sndbuf;
      z = getsockopt(m_socketfd, SOL_SOCKET, SO_SNDBUF, &amp;sndbuf, &amp;optlen);
  
      /*
      * Get socket option SON_RCVBUF:
      */
  
      optlen = sizeof rcvbuf;
      z = getsockopt(m_socketfd, SOL_SOCKET, SO_RCVBUF, &amp;rcvbuf, &amp;optlen);
  
      /*
      * Report the buffer sizes:
      */
      printf(&quot;Send buf: %d bytes\n&quot;, sndbuf);
      printf(&quot;Recv buf: %d bytes\n&quot;, rcvbuf);
  
  
  
      
      m_epollfd = epoll_create1(0);
      if (m_epollfd == -1)
      {
          perror(&quot;epoll_create&quot;);
          abort();
      }
  
      result = listen(m_socketfd, SOMAXCONN);
      if (result == -1)
      {
          perror(&quot;listen&quot;);
          abort();
      }
  
      return true;
  }
  
  void GateServer::Run()
  {
      int result = 0;
  
      struct epoll_event events[MAXEVENTS];
  
      result = AddEpollEvent(m_epollfd, m_socketfd, EPOLLIN | EPOLLET);//读入,边缘触发方式 
      if (result == -1)
      {
          perror(&quot;epoll_ctl&quot;);
          abort();
      }
  
      /* The event loop */
      while (1)
      {
          int n, i;
          n = epoll_wait(m_epollfd, events, MAXEVENTS, -1);
          HandleEvents(m_epollfd, events, n, m_socketfd);
      }
  
      close(m_socketfd);
  
  }
  
  void GateServer::HandleEvents(int epollfd, struct epoll_event *events, int num, int listenfd)
  {
      int i;
      int fd;
  
      for (i = 0; i &lt; num; i++)
      {
          fd = events[i].data.fd;
  
          if ((events[i].events &amp; EPOLLERR) ||
              (events[i].events &amp; EPOLLHUP))
          {
              /* An error has occured on this fd, or the socket is not
              ready for reading (why were we notified then?) */
  
              fprintf(stderr, &quot;epoll error\n&quot;);
              printf(&quot;events = %d\n&quot;, events[i].events);
              close(fd);
              m_nConnNum--;
              std::cout &lt;&lt; &quot;client &quot; &lt;&lt; fd &lt;&lt; &quot; disconnect. client num = &quot; &lt;&lt; m_nConnNum &lt;&lt; std::endl;
  
              continue;
          }
          else if (fd == listenfd &amp;&amp; (events[i].events &amp; EPOLLIN))
          {
          /* We have a notification on the listening socket, which
                  means one or more incoming connections. */
              HandleAccept(epollfd, listenfd);
  
          }
          else if(events[i].events &amp; EPOLLIN)
          {
          /* We have data on the fd waiting to be read. Read and
                  display it. We must read whatever data is available
                  completely, as we are running in edge-triggered mode
                  and won't get a notification again for the same
                  data. */
  
              HandleRead(epollfd, fd);
          }
          else if (events[i].events &amp; EPOLLOUT)
          {
  
          }
      }
  }
  
  void GateServer::HandleAccept(int epollfd, int listenfd)
  {
      std::cout &lt;&lt; &quot;At HandleAccept.&quot; &lt;&lt; std::endl;
      int result;
      while (1)
      {
          struct sockaddr cliaddr;
          socklen_t cliaddrlen;
          int clifd;
          char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
  
          cliaddrlen = sizeof cliaddr;
          clifd = accept(listenfd, &amp;cliaddr, &amp;cliaddrlen);
  
          if (clifd == -1)
          {
              if ((errno == EAGAIN) ||
                  (errno == EWOULDBLOCK))
              {
                  break;
              }
              else
              {
                  perror(&quot;accept&quot;);
                  break;
              }
          }
  
          m_nConnNum++;
          cout &lt;&lt; &quot;connected num = &quot; &lt;&lt; m_nConnNum &lt;&lt; endl;
  
          result = getnameinfo(&amp;cliaddr, cliaddrlen,
              hbuf, sizeof hbuf,
              sbuf, sizeof sbuf,
              NI_NUMERICHOST | NI_NUMERICSERV);
  
          if (result == 0)
          {
  //          printf(&quot;Accepted connection on descriptor %d &quot;
  //              &quot;(host=%s, port=%s)\n&quot;, clifd, hbuf, sbuf);
          }
  
  
  
          /* Make the incoming socket non-blocking and add it to the
          list of fds to monitor. */
          result = MakeSocketNonblocking(clifd);
          if (result == -1)
          {
              abort();
          }
  
          result = AddEpollEvent(epollfd, clifd, EPOLLIN | EPOLLET);
          if (result == -1)
          {
              perror(&quot;epoll_ctl&quot;);
              abort();
          }
      }
  }
  
  void GateServer::HandleRead(int epollfd, int fd)
  {
      //std::cout &lt;&lt; &quot;At HandleRead.&quot; &lt;&lt; std::endl;
      //int done = 0;
  
      while (1)
      {
          ssize_t count;
          char buf[512];
          count = read(fd, buf, sizeof(buf));
  
          if (count == -1)
          {
              /* If errno == EAGAIN, that means we have read all
              data. So go back to the main loop. */
              if (errno != EAGAIN)
              {
                  perror(&quot;read&quot;);
                  //done = 1;
              }
              break;
          }
          else if (count == 0)
          {
              /* End of file. The remote has closed the
              connection. */
              //done = 1;
              if (m_nConnNum &lt;= 0)
              {
                  perror(&quot;close&quot;);
                  abort();
              }
  
              cout &lt;&lt; &quot;client = &quot; &lt;&lt; fd &lt;&lt; &quot; disconnect.&quot; &lt;&lt; endl;
              close(fd);
              m_nConnNum--;
  
              break;
          }
          //std::cout &lt;&lt; &quot;server rec : &quot; &lt;&lt; buf &lt;&lt; std::endl;
  
          /* Write the buffer to standard output */
          int result = write(fd, buf, count);
  
          if (result == -1)
          {
              perror(&quot;write&quot;);
              abort();
          }
      }
  }
  </code></pre>