读书人

为什么小弟我的select和recv这么慢!

发布时间: 2012-03-08 13:30:13 作者: rapoo

为什么我的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;
}



------解决方案--------------------


先顶再看。
[解决办法]
iResult = select(0,&readfds,NULL,NULL,&timeout);
//////////////////////////////////////////////
第一是0??
[解决办法]
select是最大的socket+1吧
[解决办法]
select 里面的参数设置有问题

读书人网 >C语言

热点推荐