を使用してTCPサーバーを実装しましたboost::asio
。このサーバーはbasic_stream_socket::read_some
関数を使用してデータを読み取ります。read_some
私はそれが戻る前に供給されたバッファがいっぱいになることを保証しないことを知っています。
私のプロジェクトでは、区切り文字で区切られた文字列を送信しています(重要な場合)。クライアント側では、WinSock::send()
関数を使用してデータを送信しています。今、私の問題はサーバー側にあり、クライアント側から送信されたすべての文字列を取得できません。read_some
なんらかのデータを受信し、何らかの理由で残りのデータを破棄しているのではないかと思います。次の呼び出しでは、別の文字列を受信します。
TCP / IPで本当に可能ですか?
私は使用しようとしましasync_receive
たが、それは私のCPUをすべて使い果たしています。また、コールバック関数によってバッファをクリーンアップする必要があるため、プログラムで深刻なメモリリークが発生します。(私はIoService::poll()
ハンドラーを呼び出すために使用しています。そのハンドラーは、の呼び出し速度と比較して非常に遅い速度で呼び出されていますasync_read()
)。
繰り返しますが、free関数を使用しようとしましread
たが、提供しているバッファーサイズで長時間ブロックされるため、目的が解決しません。
以前のサーバーの実装では、WinSock API
を使用してすべてのデータを受信できましたWinSock::recv()
。を使用して完全なデータを受信できるように、いくつかのリードを教えてくださいboost::asio
。
これが私のサーバー側のスレッドループです
void
TCPObject::receive()
{
if (!_asyncModeEnabled)
{
std::string recvString;
if ( !_tcpSocket->receiveData( _maxBufferSize, recvString ) )
{
LOG_ERROR("Error Occurred while receiving data on socket.");
}
else
_parseAndPopulateQueue ( recvString );
}
else
{
if ( !_tcpSocket->receiveDataAsync( _maxBufferSize ) )
{
LOG_ERROR("Error Occurred while receiving data on socket.");
}
}
}
TCPSocketのreceiveData()
bool
TCPSocket::receiveData( unsigned int bufferSize, std::string& dataString )
{
boost::system::error_code error;
char *buf = new char[bufferSize + 1];
size_t len = _tcpSocket->read_some( boost::asio::buffer((void*)buf, bufferSize), error);
if(error)
{
LOG_ERROR("Error in receiving data.");
LOG_ERROR( error.message() );
_tcpSocket->close();
delete [] buf;
return false;
}
buf[len] ='\0';
dataString.insert( 0, buf );
delete [] buf;
return true;
}
TCPソケットのreceiveDataAsync
bool
TCPSocket::receiveDataAsync( unsigned int bufferSize )
{
char *buf = new char[bufferSize + 1];
try
{
_tcpSocket->async_read_some( boost::asio::buffer( (void*)buf, bufferSize ),
boost::bind(&TCPSocket::_handleAsyncReceive,
this,
buf,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred) );
//! Asks io_service to execute callback
_ioService->poll();
}
catch (std::exception& e)
{
LOG_ERROR("Error Receiving Data Asynchronously");
LOG_ERROR( e.what() );
delete [] buf;
return false;
}
//we dont delete buf here as it will be deleted by callback _handleAsyncReceive
return true;
}
非同期受信ハンドラー
void
TCPSocket::_handleAsyncReceive(char *buf, const boost::system::error_code& ec, size_t size)
{
if(ec)
{
LOG_ERROR ("Error occurred while sending data Asynchronously.");
LOG_ERROR ( ec.message() );
}
else if ( size > 0 )
{
buf[size] = '\0';
emit _asyncDataReceivedSignal( QString::fromLocal8Bit( buf ) );
}
delete [] buf;
}
クライアント側のsendData関数。
sendData(std::string data)
{
if(!_connected)
{
return;
}
const char *pBuffer = data.c_str();
int bytes = data.length() + 1;
int i = 0,j;
while (i < bytes)
{
j = send(_connectSocket, pBuffer+i, bytes-i, 0);
if(j == SOCKET_ERROR)
{
_connected = false;
if(!_bNetworkErrNotified)
{
_bNetworkErrNotified=true;
emit networkErrorSignal(j);
}
LOG_ERROR( "Unable to send Network Packet" );
break;
}
i += j;
}
}