Итак, я создал класс сокетов, который использует библиотеку boost :: asio для асинхронного чтения и записи. Это работает, но у меня есть несколько вопросов.
Вот базовый пример кода:
class Socket
{
public:
void doRead()
{
m_sock->async_receive_from(boost::asio::buffer(m_recvBuffer), m_from, boost::bind(&Socket::handleRecv, this, boost::asio::placeholders::error(), boost::asio::placeholders::bytes_transferred()));
}
void handleRecv(boost::system::error_code e, int bytes)
{
if (e.value() || !bytes)
{
handle_error();
return;
}
//do something with data read
do_something(m_recvBuffer);
doRead(); //read another packet
}
protected:
boost::array<char, 1024> m_recvBuffer;
boost::asio::ip::udp::endpoint m_from;
};
Кажется, что программа прочитает пакет, обработает его, а затем подготовится к прочтению другого. Просто.
Но что если я настрою пул потоков? Должен ли следующий вызов doRead()
быть до или после обработки прочитанных данных? Похоже, что если он установлен до do_something()
, программа может немедленно начать чтение другого пакета, а если он будет помещен после, поток связывается с тем, что делает do_something()
, что может занять некоторое время. Если я поставлю doRead()
перед обработкой, означает ли это, что данные в m_readBuffer
могут измениться во время обработки?
Кроме того, если я использую async_send_to()
, должен ли я скопировать данные для отправки во временный буфер, поскольку фактическая отправка может произойти только после того, как данные выйдут из области видимости? т.е.
void send()
{
char data[] = {1, 2, 3, 4, 5};
m_sock->async_send_to(boost::buffer(&data[0], 5), someEndpoint, someHandler);
} //"data" gets deallocated, but the write might not have happened yet!
Кроме того, когда сокет закрыт, handleRecv будет вызван с ошибкой, указывающей, что он был прерван. Если я сделаю
Socket* mySocket = new Socket()...
...
mySocket->close();
delete mySocket;
может ли это вызвать ошибку, потому что есть вероятность, что mySocket
будет удалено до того, как handleRecv()
будет вызван / завершен?