c++ socket多客户端连接

C++ socket multi client connect

本文关键字:连接 客户端 socket c++      更新时间:2023-10-16

我编写了一个在Linux中使用epoll的服务器,我想测试一下它在实际环境中可以接受多少个连接。所以我在Windows上编写了一个客户端,客户端创建了许多套接字来连接远程服务器。所以问题是,在服务器接受了大约1700个连接后,客户端创建的新套接字无法连接服务器,错误代码是10060。我把客户端复制到另一个Windows上,同时在两台PC上运行客户端,两者都得到了相同的结果。所以,服务器大约可以接受3400个连接。这个问题可能发生在windows中,我试图修复它:

[HKEY_LOCAL_MACHINE System CurrentControlSet Tcpip 服务参数)

MaxUserPort = 65534 (Decimal)

MaxHashTableSize = 65536 (Decimal)

MaxFreeTcbs = 16000 (Decimal)

但它没有帮助。这是我的服务器代码:

bool GateServer::Init(std::string &port)
{
    printf("Init to port %sn", 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 bytesn", sndbuf);
    printf("Recv buf: %d bytesn", 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 errorn");
            printf("events = %dn", 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();
        }
    }
}

您的发现并未显示您已达到任何类型的服务器限制。它们暴露了客户端每个客户端1700个连接的限制。继续测试,使用更多的客户端主机。