【发布时间】:2012-02-21 15:33:02
【问题描述】:
我正在编写一个像 Skype 这样的小型 VOIP 应用程序,它现在运行良好,但我遇到了一个非常奇怪的问题。
在一个线程中,我在一个 while(true) 循环内调用 winsock recv() 函数,每次运行两次以从套接字获取数据。 第一次调用获得 2 个字节,这些字节将被转换为(短),而第二次调用获得消息的其余部分,如下所示:
完整消息:[2 字节标题 |消息,长度由2Byte Header决定]
这些数据包大约是 49/秒,大约是 3000 字节/秒。
这些数据包的内容是转换成波形的音频数据。
使用ioctlsocket(),我确定在收到的每个“消息”(2 字节+数据)中套接字上是否有一些数据。如果在我收到线程的while(true) loop 内的消息后立即在套接字上有东西,则将收到该消息,但会丢弃该消息以防止上行延迟。
这个概念很有效,但问题是:
当我的 VOIP 程序正在运行并且当我并行下载(例如通过浏览器)文件时,套接字上总是堆积了太多数据,因为在下载时,recv() loop 似乎实际上变慢了。除了实际的 voip up/download 之外,这在每种下载/上传情况下都会发生。
我不知道这种行为从何而来,但是当我实际上取消了除我的应用程序的 voip 流量之外的所有上传/下载时,我的应用程序再次完美运行。
如果程序完美运行,ioctlsocket() 函数会将 0 写入 bytesLeft 变量,该变量在接收函数所在的类中定义。
有人知道这是从哪里来的吗?我将在下面附上我的接收功能:
std::string D_SOCKETS::receive_message(){
recv(ClientSocket,(char*)&val,sizeof(val),MSG_WAITALL);
receivedBytes = recv(ClientSocket,buffer,val,MSG_WAITALL);
if (receivedBytes != val){
printf("SHORT: %d PAKET: %d ERROR: %d",val,receivedBytes,WSAGetLastError());
exit(128);
}
ioctlsocket(ClientSocket,FIONREAD,&bytesLeft);
cout<<"Bytes left on the Socket:"<<bytesLeft<<endl;
if(bytesLeft>20)
{
// message gets received, but ignored/thrown away to throw away
return std::string();
}
else
return std::string(buffer,receivedBytes);}
【问题讨论】:
-
鉴于您的 VOIP 程序和其他程序都共享相同的带宽,难道不会期望其他程序的大量下载会降低您程序的数据接收速度吗?特别是如果您使用 TCP,并且带宽争用导致您的流的 TCP 数据包之一被丢弃......那么发送者将不得不重新发送它,同时您的应用程序将看不到任何更多数据到达。 TCP 还会自动进行发送速率限制以避免拥塞,因此这也可能是一个因素。对于 VOIP,通常最好使用 UDP...
标签: sockets winsock recv slowdown stack