C ++ socket多客户端连接

时间:2016-06-30 03:36:59

标签: c++ sockets

我编写了一个在Linux中使用epoll的服务器,我想测试它在真实环境中可以接受的连接数。所以我在Windows中编写了一个客户端,客户端创建了许多套接字来连接远程服务器。所以有一个问题,在服务器接受大约1700个连接后,客户端创建的新套接字无法连接服务器,错误代码为10060.我将客户端复制到另一个Windows并同时在2台PC上运行客户端,并且它们都得到了相同的结果。因此,服务器可以接受3400个连接。问题可能发生在Windows中,我绑定以修复它:

  

[HKEY_LOCAL_MACHINE \系统\ CurrentControlSet \服务\ TCPIP \参数]

     

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();
        }
    }
}

1 个答案:

答案 0 :(得分:0)

您的调查结果并未表明您已达到任何类型的服务器限制。它们公开了每个1700个连接的客户端限制。与更多客户端主机一起继续测试。