为什么小弟我的select和recv这么慢!
为什么我的select和recv这么慢!!
编写了一下程序,需要不断地将数据从一台计算机发送到另一台计算机,发现select和recv每次都会消耗150毫秒左右,不知道效率怎么这么低下,怎么解决呀!
软件设计是这样的,socket连接上后,双方都select对端是否有数据发送过来,
数据分为消息头和消息体,消息头是固定格式,消息体变长,因此,如果select有数据发送过来,则先recv消息头,然后直接recv消息体。
假定A机器向B机器发送了一个消息,先发送消息头,然后发消息体(分两个send函数发送),
B机器的select函数会收到数据接收请求,先收消息头(recvX),然后收消息体(recvY),消息收完后,会发送一个确认包(确认包同时携带B要发送给A的数据),确认包也是分为消息头和消息体发送。
通过这种方式,测试发现,在双方都在不断发送接收数据的过程中,
select函数耗时150毫秒左右,第一个recv(recvX)基本不耗时,第二个recv(recvY)耗时150毫秒左右,导致每收一个消息大概需要300毫秒。两个send函数基本不耗时。
也就是说,A机器与B机器之间一个完整的数据轮回大概要300毫秒,绝大多数时间都消耗在了select和recvY上了。
请问各位大虾,这到底是怎么回事,怎么能够让整个过程时间缩短呢?理想的情况最好是1-3毫秒。
网络状态是很好的,局域网100M的测试环境,数据包也很小,都不到1K。
FD_ZERO(&readfds);
FD_SET(this-> socketFd,&readfds);
iResult = select(0,&readfds,NULL,NULL,&timeout);
if ( iResult == SOCKET_ERROR )
{
//Log_Manager::WriteError( "Error read on socket. ");
return;
}
if ( ! iResult )
{
Log_Manager::WriteInfo( "等待对方250ms,未读取到对方发送的消息。 " );
ret = DealTimeout();
Log_Manager::WriteInfo( "超时处理处理完毕。 " );
continue;
}
if ( FD_ISSET(socketFd,&readfds) )
{
Log_Manager::WriteInfo( "有数据。 " );
//有数据过来
ret = RecvBufferData( &dataHead, rcvDataBuf);
if ( ret < 0 ) //SOCKET_ERROR
{
Log_Manager::WriteError( "接收数据失败,需要关闭连接。 ");
return;
}
Log_Manager::WriteInfo( "数据接收完毕。 " );
ret = SendMsgData();
Log_Manager::WriteInfo( "数据发送完毕。 " );
int CNodeCommAdapter::RecvBufferData(msg_head_for_mom_mom* lpDataHead,
char* lpData)
{
Log_Manager::WriteInfo( "开始读Head From Socket ");
int bytesRecvHead = recv( socketFd, (char*)lpDataHead, sizeof(msg_head_for_mom_mom), 0 );
if ( bytesRecvHead == SOCKET_ERROR || bytesRecvHead != sizeof(msg_head_for_mom_mom) )
return SOCKET_ERROR;
Log_Manager::WriteInfo( "读Head From Socket 完毕 ");
if ( ! lpDataHead-> dataLen )
return lpDataHead-> dataLen;
int tmpLen = lpDataHead-> dataLen;
int bytesRecvData, totalRecvData = 0;
Log_Manager::WriteInfo( "开始读Data From Socket ");
while ( tmpLen > 0 )
{
printf( "%d\n ",tmpLen);
bytesRecvData = recv( socketFd, lpData + totalRecvData , tmpLen, 0 );
Log_Manager::WriteInfo( "读Data From Socket完毕 ");
if ( bytesRecvData == SOCKET_ERROR || ! bytesRecvData)
return SOCKET_ERROR;
else
{
tmpLen -= bytesRecvData;
totalRecvData += bytesRecvData;
}
}
return lpDataHead-> dataLen;
}
------解决方案--------------------
编写了一下程序,需要不断地将数据从一台计算机发送到另一台计算机,发现select和recv每次都会消耗150毫秒左右,不知道效率怎么这么低下,怎么解决呀!
软件设计是这样的,socket连接上后,双方都select对端是否有数据发送过来,
数据分为消息头和消息体,消息头是固定格式,消息体变长,因此,如果select有数据发送过来,则先recv消息头,然后直接recv消息体。
假定A机器向B机器发送了一个消息,先发送消息头,然后发消息体(分两个send函数发送),
B机器的select函数会收到数据接收请求,先收消息头(recvX),然后收消息体(recvY),消息收完后,会发送一个确认包(确认包同时携带B要发送给A的数据),确认包也是分为消息头和消息体发送。
通过这种方式,测试发现,在双方都在不断发送接收数据的过程中,
select函数耗时150毫秒左右,第一个recv(recvX)基本不耗时,第二个recv(recvY)耗时150毫秒左右,导致每收一个消息大概需要300毫秒。两个send函数基本不耗时。
也就是说,A机器与B机器之间一个完整的数据轮回大概要300毫秒,绝大多数时间都消耗在了select和recvY上了。
请问各位大虾,这到底是怎么回事,怎么能够让整个过程时间缩短呢?理想的情况最好是1-3毫秒。
网络状态是很好的,局域网100M的测试环境,数据包也很小,都不到1K。
FD_ZERO(&readfds);
FD_SET(this-> socketFd,&readfds);
iResult = select(0,&readfds,NULL,NULL,&timeout);
if ( iResult == SOCKET_ERROR )
{
//Log_Manager::WriteError( "Error read on socket. ");
return;
}
if ( ! iResult )
{
Log_Manager::WriteInfo( "等待对方250ms,未读取到对方发送的消息。 " );
ret = DealTimeout();
Log_Manager::WriteInfo( "超时处理处理完毕。 " );
continue;
}
if ( FD_ISSET(socketFd,&readfds) )
{
Log_Manager::WriteInfo( "有数据。 " );
//有数据过来
ret = RecvBufferData( &dataHead, rcvDataBuf);
if ( ret < 0 ) //SOCKET_ERROR
{
Log_Manager::WriteError( "接收数据失败,需要关闭连接。 ");
return;
}
Log_Manager::WriteInfo( "数据接收完毕。 " );
ret = SendMsgData();
Log_Manager::WriteInfo( "数据发送完毕。 " );
int CNodeCommAdapter::RecvBufferData(msg_head_for_mom_mom* lpDataHead,
char* lpData)
{
Log_Manager::WriteInfo( "开始读Head From Socket ");
int bytesRecvHead = recv( socketFd, (char*)lpDataHead, sizeof(msg_head_for_mom_mom), 0 );
if ( bytesRecvHead == SOCKET_ERROR || bytesRecvHead != sizeof(msg_head_for_mom_mom) )
return SOCKET_ERROR;
Log_Manager::WriteInfo( "读Head From Socket 完毕 ");
if ( ! lpDataHead-> dataLen )
return lpDataHead-> dataLen;
int tmpLen = lpDataHead-> dataLen;
int bytesRecvData, totalRecvData = 0;
Log_Manager::WriteInfo( "开始读Data From Socket ");
while ( tmpLen > 0 )
{
printf( "%d\n ",tmpLen);
bytesRecvData = recv( socketFd, lpData + totalRecvData , tmpLen, 0 );
Log_Manager::WriteInfo( "读Data From Socket完毕 ");
if ( bytesRecvData == SOCKET_ERROR || ! bytesRecvData)
return SOCKET_ERROR;
else
{
tmpLen -= bytesRecvData;
totalRecvData += bytesRecvData;
}
}
return lpDataHead-> dataLen;
}
------解决方案--------------------