【问题标题】:Server's NonBlocking TCP socket taking time to stream content服务器非阻塞 TCP 套接字需要时间来传输内容
【发布时间】:2012-07-06 14:19:54
【问题描述】:

问题 - 我正在处理流服务器并使用以下方法创建了一个非阻塞套接字:

flag=fcntl(m_fd,F_GETFL);
flag|=O_NONBLOCK;
fcntl(m_fd,F_SETFL,flag);

服务器然后使用代码发送媒体文件内容:

bool SendData(const char *pData,long nSize)
{
    int fd=m_pSock->get_fd();
    fd_set write_flag;
    while(1)
    {   
        FD_ZERO(&write_flag);
        FD_SET(fd,&write_flag);
        struct timeval tout;
        tout.tv_sec=0;
        tout.tv_usec=500000;

        int res=select(fd+1,0,&write_flag,0,&tout);
        if(-1==res)
        {
            print("select() failure\n");
            return false;
        }
        if(1==res)
        {
            unsigned long sndLen=0;
            if(!m_pSock->send(pData,nSize,&sndLen))
            {
                print(socket send() failure\n");
                return false;
            }
            nSize-=sndLen;
            if(!nSize)
            return true;    //everything is sent
        }
    }
}

使用上面的代码,我正在流式传输一个说 200sec 音频文件,我希望服务器应该使用完整的 n/w 可用带宽在 2-3secs 内流式传输它(节流),但问题是服务器需要 199~200secs 来传输完整的内容。 在调试时,我评论了

m_pSock->send()

section & 试图在本地转储文件。转储文件需要 1~2 秒

问题 - 如果我使用的是非阻塞 TCP 套接字,为什么 send() 会花费这么多时间?

  • 由于数据始终可用,select() 将立即返回(正如我们在转储文件时看到的那样)。这是否意味着 send() 会受到客户端 recv() 的影响?

对此的任何输入都会有所帮助。客户行为不在我们的范围内。

【问题讨论】:

  • TCP 套接字大小为 64KB,但我发送的是 32KB。我尝试将其增加到 1MB 并获得 25-30% 的改进,但服务器仍然没有像在油门关闭模式下那样进行流式传输(即假设 15 MB 文件最多需要 2~3 秒)。刚刚测试,当客户端请求Server时,启动流媒体需要0-2毫秒。
  • “油门关闭”应该是什么意思?当您在 select() 中达到超时时,您的代码会做什么?你怎么知道客户端尽可能快地接收数据,并且没有使用流量控制来限制带宽?
  • 流式传输中的节流意味着服务器将发送内容以获得最大可用带宽。如果 Throttle 开启,服务器将根据 Frame TimeStamp 值发送内容(即在必须显示之前发送 Frame)。在 Throttle On 情况下,服务器应在“文件持续时间”时间内流式传输内容。我已经为 Throttle 编写了一个单独的代码,它工作正常。对于上面的代码,我假设永远不会发生超时,因为我们已经在函数中拥有了数据。
  • 你的意思是,如果客户端读取速度不快,至少它应该有足够的缓冲区来存储所有内容。
  • 为什么要有这么大的缓冲区?你怎么确定?你发送的文件有多大?

标签: c++ sockets select send nonblocking


【解决方案1】:

问题可能是,如果客户端使用阻塞 TCP,并且正在处理单个线程上的所有数据,没有缓冲区/队列等一直到文件的“播放器”,那么您的一方是非-blocking 只会加快速度,直到您达到 TCP/IP 协议堆栈缓冲区、NIC 缓冲区等已满的程度。然后,您最终仍然只能以客户端消耗数据的速度发送数据。记住 TCP 是一种可靠的点对点协议。

您的客户端代码在您的测试中来自哪里?是不是有人写的某种简单的测试客户端?

【讨论】:

    【解决方案2】:

    由于 TCP 输出和输入缓冲区可能比音频文件小得多,因此接收应用程序的读取速度会减慢发送速度。

    当发送方的 TCP 输出缓冲区和接收方的输入缓冲区都已满时,发送方的 TCP 堆栈无法接收到发送方的任何数据。所以发送将被阻止,直到有空间。

    如果接收方读取 TCP 流的速度与播放所需的数据相同。然后传输大约需要 200 秒。或者少一点。

    这可以通过在接收端使用应用层缓冲来避免。

    【讨论】:

      【解决方案3】:

      您的客户端可能正在做一些缓冲以避免网络抖动,但它可能仍在实时播放音频文件。因此,文件传输速率与客户端使用数据的速率相匹配。由于是 200 秒的音频文件,所以大约需要 200 秒才能完成传输。

      【讨论】:

      • 增加操作系统缓冲区有帮助吗?
      • @user1409528 这意味着您可以更快地将数据推送到内核缓冲区,但不会提高网络上的传输速度。
      • @user1409528:您看到多少改进取决于客户端和服务器的 TCP 配置。如果他们被配置为扩大他们的窗口大小,并且如果 TCP 窗口大小以某种方式扩大到处理 1 分钟的音频,那将解释你的速度提高了 25%-30%。
      猜你喜欢
      • 2016-01-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多