Я реализовал TCP-сервер, используя boost::asio
. Этот сервер использует функцию basic_stream_socket::read_some
для чтения данных. Я знаю, что read_some
не гарантирует, что поставляемый буфер будет заполнен до его возврата.Данные теряются в TCP/IP с boost :: asio :: read_some?
В моем проекте я отправляю строки, разделенные разделителем (если это имеет значение). На стороне клиента я использую функцию WinSock::send()
для отправки данных. Теперь моя проблема на стороне сервера. Я не могу получить все строки, которые были отправлены с клиентской стороны. Подозреваю, что read_some
по некоторым причинам получает некоторые данные и отбрасывает оставшиеся данные. Затем снова в следующем вызове его получение другой строки.
Возможно ли это в TCP/IP?
Я попытался использовать async_receive
, но это весь мой процессор, так как буфер должен быть очищен функцией обратного вызова, что вызывает серьезную утечку памяти в моей программе. (Я использую IoService::poll()
для вызова обработчика. Этот обработчик вызывается с очень низкой скоростью по сравнению со скоростью звонка async_read()
).
Снова я попытался использовать бесплатную функцию 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.");
}
}
}
receiveData() в TcpSocket
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;
}
receiveDataAsync в TCP сокет
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;
}
}
Если вы хотите получить помощь, разместите свой код. Включите код сервера, а также код клиента, потому что проблема может быть в том или и в другом. –
Обновлено кодом. –