У меня есть пара вопросов, касающихся Boost ASIO.
Я сталкиваюсь с проблемой, когда мои клиенты могут подключаться к серверу и асинхронно отправлять данные, но не могут ничего получить обратно. Обратный вызов async_write получает ошибку: «Указанный дескриптор файла недействителен». Я нахожу это странным по нескольким причинам:
Еще немного информации …
TCP-сокеты.
Я использую Boost и Allegro бок о бок, и используются потоки Boost и Allegro. У меня есть io_service, работающий в потоке Boost, примерно так (сервер и клиент):
boost::asio::io_service::work work( io_service );
boost::thread io_thread( boost::bind( &boost::asio::io_service::run, &io_service ) );
и это называется еще до того, как я создаю сокеты.
Потоки Allegro содержат циклы событий Allegro, ничего особенного там нет.
Мне бы не хотелось размещать исходный код, он довольно большой и сложный, и я бы не стал пытаться упростить его до базового случая. Я могу, если это необходимо, хотя.
Мои сокеты обернуты классом, в котором создается и передается общий указатель, а не обычный указатель (не уверен, если это имеет значение, я новичок в Boost).
Спасибо за любую помощь, которую вы можете оказать, чтобы определить, почему я не могу переписываться с клиентами, к которым я подключился.
Нил
РЕДАКТИРОВАТЬ: Запрошенные сегменты кода:
Функции async_read / write (сервер) и обратного вызова:
void ServerConnection::async_read()
{
if( this->m_socket.is_open() == false )
{
std::cerr << "socket closed... (read)\n";
}
boost::asio::async_read( this->m_socket,
boost::asio::buffer( &m_input, sizeof( m_input ) ),
boost::bind( &ServerConnection::read_callback,
shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred ) );
}
void ServerConnection::async_write(const packet_list &packet, packet_id id, uint8_t rr)
{
this->m_output.data = packet;
this->m_output.head.opcode = id;
this->m_output.head.sender_id = 0;
this->m_output.head.response_required = rr;
if( this->m_socket.is_open() )
{
std::cerr << "socket closed... (write)\n";
}
boost::asio::async_write( this->m_socket,
boost::asio::buffer( &m_output, sizeof( m_output ) ),
boost::bind( &ServerConnection::write_callback,
shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred ) );
}
void ServerConnection::read_callback( const boost::system::error_code &error,
size_t /*read_count*/ )
{
if( error )
{
std::cerr << "Error reading: " << error.message() << std::endl;
return;
}
std::cerr << "Server reading data...\n";
if( this->m_event_dispatcher != nullptr )
{
ALLEGRO_EVENT event;
if( m_input.head.opcode == C_ACCEPT )
{
event.type = 513;
}
else
{
event.type = 512;
event.user.data1 = (intptr_t)&m_input;
}
al_emit_user_event( this->m_event_dispatcher, &event, nullptr );
}
else
{
std::cerr << "Why is this null....\n";
}
async_read();
}
void ServerConnection::write_callback(const boost::system::error_code &error,
size_t /*write_count*/ )
{
// After a write, we don't need to do anything except error checking.
if( error.value() )
{
std::cerr << "Error writing to client. " << error.message() << std::endl;
}
}
Задача ещё не решена.
Других решений пока нет …