#c #ssl #asynchronous #boost-asio #asio
#c #ssl #асинхронный #boost-asio #asio
Вопрос:
Я пытаюсь написать асинхронный сервер с использованием asio с зашифрованными сокетами SSL. В настоящее время у меня есть код, который не использует SSL, и после выполнения этого руководства у меня есть общее представление о том, как принимать сокет SSL, однако я не знаю, как адаптировать этот код для приема SSL-соединения:
void waitForClients() {
acceptor.async_accept(
[this](std::error_code ec, asio::ip::tcp::socket socket) {
if (!ec) {
Conn newConn = std::make_shared<Connection>(ctx, std::move(socket));
connections.push_back(newConn);
} else {
std::cerr << "[SERVER] New connection error: " << ec.message() << "n";
}
waitForClients();
}
);
}
//this is how the tutorial shows to accept a connection
ssl_socket socket(io_context, ssl_context);
acceptor.accept(socket.next_layer());
Проблема в том, что обратный вызов for acceptor.async_accept
выдает обычный asio::ip::tcp::socket
, а не an asio::ssl::ssl_socket<asio::ip::tcp::socket>
, и я не могу найти никакой документации, которая предполагает, что существует метод async_accept
ввода SSL-сокета таким образом. Единственный метод, который я видел, — это сначала создать сокет, а затем принять его впоследствии, что невозможно сделать таким асинхронным способом.
Любая помощь будет высоко оценена.
Комментарии:
1. Если у вас уже есть код, который делает это для сокета, отличного от SSL, вы можете просто использовать те же вещи, чтобы принять сокет SSL. Если вопрос заключается в том, как использовать потоки или писать асинхронный код в целом на c , тогда удалите все сокеты и asio из вашего вопроса и сделайте базовый пример запуска / присоединения к потоку. Если ни один из них не применяется, вам следует уточнить свой вопрос.
2. @super Я попытался добавить пояснения к своему вопросу, но я не совсем уверен, что неясно, если есть что-то конкретное, было бы неплохо узнать.
3. Я никогда не использовал это сам, но быстрый взгляд на документацию показывает
typedef ssl::stream<tcp::socket> ssl_socket;
. Такимssl_socket
образом, в данном случае это просто оболочка вокруг обычного сокета. Итак, обычный сокет — это то, что вам нужно. Просто оберните его вssl::stream.
4. @super Я не был уверен, смогу ли я создать an
ssl_socket
из существующего сокета, а не принимать подключение к anssl_socket
напрямую. Но стоит попробовать5. Я действительно не вижу проблемы. В
acceptor.accept(socket.next_layer());
вы передаете сокет вaccept
. Почему вы не можете просто сделать то же самое дляasync_accept
?
Ответ №1:
Я решил проблему, поняв, что вторым аргументом конструктора asio::ssl::stream<asio::ip::tcp::socket>
является любой инициализатор для базового типа asio::ip::tcp::socket
. Таким образом, проблема может быть решена:
void waitForClients() {
acceptor.async_accept(
[this](std::error_code ec, asio::ip::tcp::socket socket) {
if (!ec) {
//initialise an ssl stream from already created socket
asio::ssl::stream<asio::ip::tcp::socket> sslStream(sslCtx, std::move(socket);
//then pass it on to be used
Conn newConn = std::make_shared<Connection>(ctx, sslStream);
connections.push_back(newConn);
} else {
std::cerr << "[SERVER] New connection error: " << ec.message() << "n";
}
waitForClients();
}
);
}
Комментарии:
1. Я просто пытался убедить вас в информации, которую вы предоставляете в комментариях. Вы сказали, что речь идет об управлении временем жизни. Я только изложил это для вас. Я почти уверен, что это именно то, что сказал вам мой второй комментарий. Но, эй, отличная работа по ее решению.
2. Оставляя комментарий, чтобы помочь другим в будущем: похоже, порядок аргументов для инициализатора ssl::stream был изменен (?), Поэтому std::move(сокет) теперь должен быть перед контекстом