【问题标题】:TCP connecting to server is slow?TCP连接到服务器很慢?
【发布时间】:2015-11-14 13:00:35
【问题描述】:

我正在运行一个快速接受 java 客户端的 TCP 服务器。但是 c++ 客户端确实需要 ~1Second 才能连接到它。 (使用范围时间记录器)我所做的是,我在发送之前连接到服务器并完成通信,我关闭了套接字,下次我发送一些东西时,我执行相同的过程。

for 循环连接到套接字真的很慢。我该如何改善这个?! (连接很慢)

是客户端还是这里的服务器?如果它可能是服务器,我想知道如果 java 客户端连接它为什么不慢

bool JIMDBClient::connect()
{
    WSADATA wsaData;
    m_sock = INVALID_SOCKET;
    struct addrinfo* result = nullptr, *ptr = nullptr, hints;

    int iResult;

    /* Initialisiere TCP für Windows ("winsock"). */
    WORD wVersionRequested;

    // Initialize Winsock
    iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (iResult != 0)
    {
        printf("WSAStartup failed with error: %d\n", iResult);
        m_connected = false;
        return false;
    }

    ZeroMemory(&hints, sizeof(hints));
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;

    // Resolve the server address and port
    iResult = getaddrinfo(m_host.c_str(), m_port.c_str(), &hints, &result);
    if (iResult != 0)
    {
        printf("getaddrinfo failed with error: %d\n", iResult);
        WSACleanup();
        m_connected = false;
        return false;
    }

    // Attempt to connect to an address until one succeeds
    for (ptr = result; ptr != nullptr; ptr = ptr->ai_next) // this is slow
    {
        // Create a SOCKET for connecting to server
        m_sock = socket(ptr->ai_family, ptr->ai_socktype,
                        ptr->ai_protocol);
        if (m_sock == INVALID_SOCKET)
        {
            printf("socket failed with error: %ld\n", WSAGetLastError());
            WSACleanup();
            m_connected = false;
            return false;
        }

        // Connect to server.
        iResult = ::connect(m_sock, ptr->ai_addr, static_cast<int>(ptr->ai_addrlen));
        if (iResult == SOCKET_ERROR)
        {
            closesocket(m_sock);
            m_sock = INVALID_SOCKET;
            continue;
        }
        break;
    }

    freeaddrinfo(result);

    if (m_sock == INVALID_SOCKET)
    {
        WSACleanup();
        m_connected = false;
        return false;
    }

    if(!handShake()) //only takes around 450µS !
    {
        LOG_WARN << "handshake failed";
        WSACleanup();
        m_connected = false;
        return false;
    }

    m_connected = true;
    return m_connected;
}

【问题讨论】:

  • 它是否连接到您在result 中返回的第一个协议?还是尝试几个?哪些协议有效,哪些无效?
  • 如果我打印它,它确实连接到第二个“6”。这将适合服务器端hints.ai_protocol = IPPROTO_TCP;
  • 那么是延迟调用失败,还是调用成功? (我猜是前者。)失败的调用中的参数是什么?也许您可以过滤或排序结果,以使您更有可能在第一次尝试时成功。甚至尝试并行多个连接。
  • 您的服务器是使用 IPv4 还是 6 或两者兼而有之?
  • 你可以使用 async-io 来加快速度

标签: c++ sockets tcp winsock2


【解决方案1】:

如果您知道您的服务器仅支持 IPv4 或 IPv6,您可以在传递给 getaddrinfo 的提示中这样说:

hints.ai_family = AF_INET; // Or AF_INET6

【讨论】:

  • AF_INET6 是 23,AF_INET 是 2 - 所以后者似乎是你想要的。
  • 右服务器端是 AF_INET,我在客户端说 unspec,这会导致长时间搜索。他检查的每个“版本”都需要 1 秒。
  • 更好的解决方案可能是让您的服务器同时支持 IPv4 和 IPv6。
  • 我该怎么做?我可以以某种方式在提示中设置它还是我需要在 2 个套接字上监听?
  • 这听起来像是一个不同的问题——我不知道你的服务器代码是什么样的。恐怕我实际上并不知道答案。
猜你喜欢
  • 1970-01-01
  • 2014-09-15
  • 2016-08-26
  • 1970-01-01
  • 1970-01-01
  • 2012-07-30
  • 2020-09-17
  • 2018-11-24
  • 2017-02-24
相关资源
最近更新 更多