2016-06-30 4 views
-3

Я пишу Сервер, который использует epoll в Linux, и я хочу проверить, сколько подключений оно может принять в реальной среде. Поэтому я пишу клиент в Windows, клиент создает много сокетов для подключения удаленного сервера. Поэтому возникает вопрос: после того, как сервер принимает около 1700 подключений, новый сокет, созданный клиентом, не может подключиться к серверу, а код ошибки - 10060. Я копирую клиент в другую Windows и запускаю клиент на 2 ПК одновременно, и оба они получают одинаковый результат. Таким образом, сервер может принимать 3400 подключений. Проблемы могут иметь место в окнах, и я привязал, чтобы исправить это:C++ socket multi client connect

[HKEY_LOCAL_MACHINE \ System \ CurrentControlSet \ Services \ Tcpip \ Parameters]

MaxUserPort = 65534 (десятичное)

MaxHashTableSize = 65536 (десятичное)

MaxFreeTcbs = 16000 (десятичное)

Но это не помогает. Существует мой код сервера:

bool GateServer::Init(std::string &port) 
{ 
    printf("Init to port %s\n", 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, &sndbuf, &optlen); 

    /* 
    * Get socket option SON_RCVBUF: 
    */ 

    optlen = sizeof rcvbuf; 
    z = getsockopt(m_socketfd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, &optlen); 

    /* 
    * Report the buffer sizes: 
    */ 
    printf("Send buf: %d bytes\n", sndbuf); 
    printf("Recv buf: %d bytes\n", rcvbuf); 




    m_epollfd = epoll_create1(0); 
    if (m_epollfd == -1) 
    { 
     perror("epoll_create"); 
     abort(); 
    } 

    result = listen(m_socketfd, SOMAXCONN); 
    if (result == -1) 
    { 
     perror("listen"); 
     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("epoll_ctl"); 
     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 < num; i++) 
    { 
     fd = events[i].data.fd; 

     if ((events[i].events & EPOLLERR) || 
      (events[i].events & EPOLLHUP)) 
     { 
      /* An error has occured on this fd, or the socket is not 
      ready for reading (why were we notified then?) */ 

      fprintf(stderr, "epoll error\n"); 
      printf("events = %d\n", events[i].events); 
      close(fd); 
      m_nConnNum--; 
      std::cout << "client " << fd << " disconnect. client num = " << m_nConnNum << std::endl; 

      continue; 
     } 
     else if (fd == listenfd && (events[i].events & EPOLLIN)) 
     { 
     /* We have a notification on the listening socket, which 
       means one or more incoming connections. */ 
      HandleAccept(epollfd, listenfd); 

     } 
     else if(events[i].events & 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 & EPOLLOUT) 
     { 

     } 
    } 
} 

void GateServer::HandleAccept(int epollfd, int listenfd) 
{ 
    std::cout << "At HandleAccept." << 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, &cliaddr, &cliaddrlen); 

     if (clifd == -1) 
     { 
      if ((errno == EAGAIN) || 
       (errno == EWOULDBLOCK)) 
      { 
       break; 
      } 
      else 
      { 
       perror("accept"); 
       break; 
      } 
     } 

     m_nConnNum++; 
     cout << "connected num = " << m_nConnNum << endl; 

     result = getnameinfo(&cliaddr, cliaddrlen, 
      hbuf, sizeof hbuf, 
      sbuf, sizeof sbuf, 
      NI_NUMERICHOST | NI_NUMERICSERV); 

     if (result == 0) 
     { 
//   printf("Accepted connection on descriptor %d " 
//    "(host=%s, port=%s)\n", 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("epoll_ctl"); 
      abort(); 
     } 
    } 
} 

void GateServer::HandleRead(int epollfd, int fd) 
{ 
    //std::cout << "At HandleRead." << 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("read"); 
       //done = 1; 
      } 
      break; 
     } 
     else if (count == 0) 
     { 
      /* End of file. The remote has closed the 
      connection. */ 
      //done = 1; 
      if (m_nConnNum <= 0) 
      { 
       perror("close"); 
       abort(); 
      } 

      cout << "client = " << fd << " disconnect." << endl; 
      close(fd); 
      m_nConnNum--; 

      break; 
     } 
     //std::cout << "server rec : " << buf << std::endl; 

     /* Write the buffer to standard output */ 
     int result = write(fd, buf, count); 

     if (result == -1) 
     { 
      perror("write"); 
      abort(); 
     } 
    } 
} 
+0

Не звучит как проблема с кодированием, или это так? – Soren

+0

Какой тип, на котором он похож? – nighcate

+0

Неясно, какой из параметров реестра может повлиять на вашу проблему. Было бы более интересно увидеть ваш код и, в частности, код сервера. – EJP

ответ

0

Ваши данные не показывают, что вы достигли предела сервера любого рода. Они выставляют клиент ограничений по 1700 подключений. Продолжайте тестирование с большим количеством клиентских хостов.

+0

Вы правы, но у меня больше нет клиентских хостов. Поэтому мне интересно, можно ли протестировать 2 ПК. – nighcate