【发布时间】: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