Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sockets 奇怪的Winsock recv()减速_Sockets_Winsock_Recv_Slowdown_Stack - Fatal编程技术网

Sockets 奇怪的Winsock recv()减速

Sockets 奇怪的Winsock recv()减速,sockets,winsock,recv,slowdown,stack,Sockets,Winsock,Recv,Slowdown,Stack,我正在编写一个像Skype这样的VOIP应用程序,它现在运行得很好,但我遇到了一个非常奇怪的问题 在一个线程中,我将在一段时间内(true)每次运行两次winsock recv()函数,以从套接字获取数据。 第一个调用获取2个字节,这些字节将被转换为(短)字节,而第二个调用获取消息的其余部分,如下所示: 完整消息:[2字节头|消息,长度由2字节头决定] 这些数据包约为49字节/秒,约为3000字节/秒 这些数据包的内容是转换成波形的音频数据 通过ioctlsocket()我可以确定在我收到的每个

我正在编写一个像Skype这样的VOIP应用程序,它现在运行得很好,但我遇到了一个非常奇怪的问题

在一个线程中,我将在一段时间内(true)每次运行两次winsock recv()函数,以从套接字获取数据。 第一个调用获取2个字节,这些字节将被转换为(短)字节,而第二个调用获取消息的其余部分,如下所示:

完整消息:[2字节头|消息,长度由2字节头决定]

这些数据包约为49字节/秒,约为3000字节/秒

这些数据包的内容是转换成波形的音频数据

通过
ioctlsocket()
我可以确定在我收到的每个“消息”(2字节+数据)中,套接字上是否有一些数据。如果在线程的
while(true)循环中收到消息之后,套接字上就出现了一些东西,则会接收到消息,但会丢弃消息以防止上溯延迟

这一概念非常有效,但问题是:

当我的VOIP程序运行时,当我并行下载(例如通过浏览器)一个文件时,套接字上总是堆积着太多的数据,因为在下载时,
recv()循环
实际上似乎变慢了。除了实际的voip启动/下载之外,在每种下载/上传情况下都会发生这种情况

我不知道这种行为是从哪里来的,但当我实际上取消了我应用程序的voip流量之外的每一次启动/下载时,我的应用程序又能完美地工作了

如果程序运行正常,
ioctlsocket()

有人知道这是从哪里来的吗?我将在下面附加我的接收功能:

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);}
std::string D_SOCKETS::receive_message(){
recv(ClientSocket,(char*)&val,sizeof(val),MSG_WAITALL);
receivedBytes=recv(ClientSocket、buffer、val、MSG_WAITALL);
if(接收字节数!=val){
printf(“短:%d数据包:%d错误:%d”,val,receivedBytes,WSAGetLastError());
出口(128);
}
ioctlsocket(ClientSocket、FIONREAD和bytesleet);

cout没有必要使用
ioctlsocket()
丢弃数据。这表明协议设计中存在错误。假设您使用的是TCP(您没有说),如果您的2byte标头始终准确,则不应存在任何剩余数据。在读取2byte标头并读取指定的字节数后,随后收到的下一个字节将构成您的下一条消息,不应仅因为它存在而丢弃

ioctlsocket()
报告的可用字节数更多,这意味着您接收消息的速度比从套接字读取消息的速度快。请让您的读取代码运行得更快,不要因为速度慢而丢弃好数据

您的读取模型效率不高。与其先读取2个字节,然后读取X个字节,然后读取2个字节等等,不如使用更大的缓冲区一次从套接字读取更多原始数据(使用
ioctlsocket()
了解可用字节数,然后一次至少读取该字节数并将其附加到缓冲区的末尾),然后解析缓冲区中的完整消息,然后再次从套接字读取更多原始数据。一次读取的数据越多,接收数据的速度越快


为了进一步加快代码速度,也不要直接在循环中处理消息。改为在另一个线程中处理。让读取循环将完整的消息放入队列并返回读取,然后在消息可供处理时从队列中拉出一个处理线程。

鉴于您的VOIP程序和另一个程序都共享相同的带宽,难道不认为另一个程序的大量下载会使您的程序的数据接收速度降低一些吗?特别是如果您使用TCP,并且带宽争用会导致流中的一个TCP数据包被丢弃…那么发送方将不得不重新发送它,同时,你的应用程序将看不到更多的数据到达。此外,TCP会自动调节发送速率以避免拥塞,因此这可能也是一个因素。对于VOIP,通常最好使用UDP…+1来尝试改变“不寻常”设计的方向。非常感谢你的帮助!我已经去医院很长时间了,所以我无法回信。我按照Remy Lebeau所说的那样构建了它,而且它的工作方式很有魅力。需要切换到UDP,因为Jeremy Friesner所说的,因为发送速率限制,因为我的应用程序显然在我上传数据时看不到更多的数据,例如,在尝试音频程序时文件。