【问题标题】:C++ TCP Socket Exponential Increasing DelayC++ TCP 套接字指数增加延迟
【发布时间】:2014-03-23 11:13:48
【问题描述】:

我的 TCP 服务器的数据包传输延迟增加似乎存在问题。现在,该服务器必须是 TCP,因为 UDP 被防火墙阻止(这是一种客户端-服务器-客户端类型的通信)。我也知道像我一样发送带有浮点整数的结构是非常不可移植的,但是,在可预见的将来,该系统将运行 Windows 客户端到 Windows 服务器到 Windows 客户端。

问题是这样的:客户端开始从另一个客户端正确接收数据,但是,延迟会呈指数级恶化(大约 3 分钟后,数据包落后了近 30 秒 - 但正确,当他们到达时)。我研究了它并在 Microsoft 页面上找到了一个答案,解释它是由于完整的发送缓冲区,但是,它们的 setsockopt 语法与记录的示例不匹配,所以也许我错了。

无论如何,任何建议都将不胜感激:

服务器相关部分:

(当 accept() 被调用时:)

int buff_size = 2048000;
int nodel = 1;
setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char*)&buff_size, sizeof(int));
setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char*)&buff_size, sizeof(int));
setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char*)&nodel, sizeof(nodel));

消息重定向循环:

    if (gp->curr_pilot < sz && gp->users[gp->curr_pilot].pilot == TRUE) {
            char* pbuf = new char[1024];
            int recvd = recv(gp->users[gp->curr_pilot].sockfd_data, pbuf, 1024, NULL);
            if (recvd > 0) {
                for (int i = 0; i < sz; i++) {
                    if (i != gp->curr_pilot && gp->users[i].unioned == TRUE)
                        send(gp->users[i].sockfd_data, pbuf, recvd, NULL);
                }
            }
            delete[] pbuf;
        }

客户端(发送时设置了主机,我的代码确实设置了它):

(数据是由客户端写入的双精度结构,cdata 是写入客户端的副本)。

    while (kill_dataproc == FALSE) {
    if (master == TRUE) {
        char* buff = new char[1024];
        int packet_signer = 1192;
        memcpy_s(buff, intsz, &packet_signer, intsz);
        memcpy_s((void*)(buff + intsz), sz, data, sz);
        send(server_sock, buff, buffsize, NULL);
        delete[] buff;
    }
    else {          
        char* buffer = new char[1024];
        int recvd = recv(server_sock, buffer, 1024, MSG_PEEK);
        if (recvd > 0) {
            int newpacketsigner = 0;
            memcpy_s(&newpacketsigner, intsz, buffer, intsz);

            if (newpacketsigner == 1192) {
                if (recvd >= buffsize) {
                    char* nbuf = new char[buffsize];
                    int recvd2 = recv(server_sock, nbuf, buffsize, NULL);
                    int err = WSAGetLastError();

                    memcpy_s(&newpacketsigner, intsz, nbuf, intsz);
                    memcpy_s(cdata, sz, (void*)(nbuf + intsz), sz);
                    //do things w/ the struct                       
                    delete[] nbuf;                      
                }
            }
            else                
                recv(server_sock, buffer, 1024, NULL);
        }
        delete[] buffer;
    }

    Sleep(10);
}

同样,对 setsockopt 和客户端套接字的调用相同,所有套接字(服务器和客户端)都是非阻塞的。

【问题讨论】:

  • 我建议简化您的程序,直到问题消失(那么原因可能是您删除的问题)或者它足够简单和完整以供其他人理解。您可以尝试从删除对我来说可疑的 Sleep(10) 开始。
  • Sleep(10) 是为了防止此循环占用客户端系统上 100% 的 CPU 使用率。
  • 如果您需要休眠以不吸 CPU,那么您的非阻塞 I/O 完全错误(您说套接字是非阻塞的)。
  • @SteffenUllrich 他到底在哪里说的?
  • 这里是正确的 - 他们是。那我该怎么办呢?

标签: c++ sockets tcp buffer delay


【解决方案1】:

您假设您的读取正在填充缓冲区。他们只需要传输至少一个字节。你需要循环。

因此,您有未读数据备份并停止发送方。

NB 这些接收缓冲区大于 64k,因此除非在连接套接字之前设置它们,否则它们可能无法使用。对于服务器,您需要在侦听套接字上设置接收缓冲区大小。接受的套接字将继承它。如果您不按照他的方式进行,则窗口缩放将不会生效,因此无法宣传 > 64k 的窗口(除非平台默认启用窗口缩放)。

【讨论】:

  • 我在循环 - 它接收到一些东西,如果它未被识别,它会丢弃它,否则,它会使用它。
  • 您正在循环,但您无法确保收到 1024 字节或任何缓冲区大小或消息大小。你只是在做相当随机的recv() 电话。您的代码基本上根本不起作用。
猜你喜欢
  • 2013-03-13
  • 1970-01-01
  • 1970-01-01
  • 2018-10-12
  • 2010-09-30
  • 2015-12-15
  • 2021-04-16
  • 1970-01-01
  • 2016-04-19
相关资源
最近更新 更多