Я столкнулся с проблемой с Poco::HTTPSClientSession
и не знаю, как справиться с этим.
HTTPS-соединение с сервером устанавливается с использованием Poco::HTTPSClientSession
учебный класс. Установление соединения, обмен ключами, первоначальный обмен данными работает хорошо.
Клиент отправляет один запрос сразу после установления сеанса. Функция постоянных подключений HTTP 1.1 используется (то есть соединение остается открытым в течение некоторого времени для обработки дополнительных запросов). Сервер ждет одну минуту — по этому соединению дальнейшие запросы не принимаются — затем отправляет close_notify
и закрывает соединение (с TCP FIN). Примерно через две минуты после этого клиент хочет отправить следующий запрос. Клиент отправляет close_notify
и закрывает соединение с TCP RST.
ИМХО поведение клиента не правильно. Как вы можете прочитать в RFC 6101 5.4.1. Уведомления о закрытии, другая сторона должна закрыть соединение немедленно:
Требуется, чтобы другая сторона ответила собственным предупреждением close_notify и немедленно закрыла соединение, отбрасывая все ожидающие записи.
Я не уверен, как справиться с этим с Поко. Для меня это выглядит так, что существует необходимость в некоторой обработке обратного вызова (в тот момент, когда сервер отправляет close_notify
). Проблема заключается в том, что, поскольку метод socket () защищен внутри Poco::HTTPSClientSession
нет возможности установить такой close_notify
обработчик — и даже я не знаю, есть ли соответствующий обратный вызов для этого.
Можете ли вы намекнуть мне класс / функцию, чтобы использовать, чтобы правильно закрыть HTTPS-соединение клиента, когда сервер отправляет close_notify
? [Дополнение после ответа от Иоахима Пилеборга]: Есть ли необходимость наследовать от Poco::HTTPSClientSession
правильно обращаться с close_notify
?
С уважением, Андреас
Это старый вопрос, но, поскольку нет приемлемого ответа, я привожу здесь свое решение, если оно может кому-то помочь.
Сделайте это перед отправкой запроса на сервер.
if (mySession->socket().poll(0, Poco::Net::Socket::SELECT_READ) && (mySession->socket().receiveBytes(NULL,0) == 0)) {
mySession->reset();
}
Из документации Poco:
bool poll(const Poco::Timespan& timeout, int mode) const;
/// Determines the status of the socket, using a
/// call to select().
///
/// The mode argument is constructed by combining the values
/// of the SelectMode enumeration.
///
/// Returns true if the next operation corresponding to
/// mode will not block, false otherwise.
int receiveBytes(void* buffer, int length, int flags = 0);
/// Receives data from the socket and stores it
/// in buffer. Up to length bytes are received.
///
/// Returns the number of bytes received.
/// A return value of 0 means a graceful shutdown
/// of the connection from the peer.
///
/// Throws a TimeoutException if a receive timeout has
/// been set and nothing is received within that interval.
/// Throws a NetException (or a subclass) in case of other errors.
Метод poll с режимом select_read вернет true, если у вас есть открытый читаемый сокет.
Используйте receiveBytes, чтобы прочитать корректное завершение работы на стороне сервера, а затем сбросить сокет для следующих запросов.
Других решений пока нет …