0

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

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
        }
    }
}

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

m_pSock->发送()

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

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

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

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

4

3 回答 3

1

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

于 2012-07-06T06:31:44.047 回答
0

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

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

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

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

于 2012-07-06T06:40:49.263 回答
0

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

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

于 2012-07-06T06:44:21.143 回答