Я пытаюсь подружиться с asio и SSL.Все идет хорошо, но одно доставляет неудобства: как определить, закрыто ли одноранговое соединение, и отличить его от ситуации, когда одноранговый узел просто делает короткий перерыв при отправке данных, чтобы продолжить его через несколько секунд?
- boost 1.48
- OpenSSL 1.0.0e
- Скомпилирован в 32-битный код с использованием VS10
- Работает на W7 x64.
Моя путаницаПроисходит от того, что поведение asio отличается для обычных сокетов и SSL-потоков.Если я использую tcp :: socket - я получаю ошибку EOF при закрытии соединения.Но для boost :: asio :: ssl :: stream - дело не в этом.Вместо этого async_read_some возвращает 0 при передаче байтов, а если я пытаюсь продолжить чтение из потока SSL - возвращает short_error (http://www.boost.org/doc/libs/1_47_0/doc/html/boost_asio/overview/core/streams.html).
Итак, возникает вопрос: ожидается ли это поведение илиЯ что-то неправильно настроил?
Фрагмент кода клиента:
class client
{
public:
// bla-bla-bla-bla-bla ....
//
void handle_write(const boost::system::error_code& error)
{
if (!error)
{
socket_.async_read_some(boost::asio::buffer(reply_, max_length),
boost::bind(&client::handle_read, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
else
{
std::cout << "Write failed: " << error.message() << "\n";
}
}
void handle_read(const boost::system::error_code& error,
size_t bytes_transferred)
{
std::cout << "Bytes transfered: " << bytes_transferred << "\n";
if (!error)
{
std::cout << "Reply: ";
std::cout.write(reply_, bytes_transferred);
std::cout << "\n";
std::cout << "Reading...\n";
socket_.async_read_some(boost::asio::buffer(reply_, max_length),
boost::bind(&client::handle_read, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
else if (0 != bytes_transferred)
{
std::cout << "Read failed: " << error.message() << ":"
<< error.value() << "\n";
}
}
private:
boost::asio::ssl::stream<boost::asio::ip::tcp::socket> socket_;
boost::asio::streambuf request_;
char reply_[max_length];
};
Если мы удалим if (0! = Bytes_transferred), мы получим "краткое чтение": (.
Если мы будем использовать код как-ai, вывод будет выглядеть примерно так:
Запрос:
GET / HTTP / 1.0
Cookie: Nama-nama = Vala-vala
Передано байт: 1024
Ответ: HTTP / 1.0 200 ok Тип контента: text / html
..... bla-bla-бла ....
Чтение ... Передано байтов: 1024
..... бла-бла-бла .... ..... бла-бла-бла....
Чтение ... Передано байтов: 482
..... бла-бла-бла ....
Чтение ...
Передано байтов: 0
В то же время, если вместо async_read_some мы напишем код, что за обычный сокет wплохо вернет EOF:
boost::asio::async_read(socket_, response_,
boost::asio::transfer_at_least(1),
boost::bind(&client::handle_read_content, this,
boost::asio::placeholders::error));
тогда для SSL-сокета мы получим 0 в качестве переданных байтов, а затем short_read.
Я знаю, что нет способа обнаружить разрыв соединения в случае, еслиpeer, например, был просто отключен от сети.Но как обнаружить явное чистое отключение однорангового узла от ситуации, когда одноранговый узел просто не отправляет данные в течение некоторого времени, но, может быть, сделает это немного позже?
Или, может быть, я что-то не понимаю?
WBR, Андрей
Некоторое addentum: SSL / TLS имеет примечание, чтобы сообщить другой стороне о закрытии соединения.Это оповещение close_notify.Кроме того, базовый сокет TCP может быть закрыт.
Итак, в основном мой вопрос таков: почему в тех же условиях (сокет TCP был закрыт четко) я получаю EOF в случае tcp :: socket и не получаючто-нибудь для boost :: asio :: ssl :: stream.
Это ошибка или функция asio?
Еще одно добавление: по некоторым причинам asio не дал мне EOF, даже если SSLполучить close_notify, ни нижележащий сокет TCP не был закрыт.
Да, я могу обнаружить потерянные соединения по таймауту.Но как определить правильно закрытые SSL-соединения?Получая short_read?