gpt4 book ai didi

c++ - 写入:执行 boost::asio::async_write 时出现单元化错误

转载 作者:行者123 更新时间:2023-11-30 01:46:55 34 4
gpt4 key购买 nike

我已经指定使用 boost::asio 创建一个 HTTPS 服务器,所以我确实花了一些时间在互联网上,找到了一个资源,解释了我们如何将 boost HTTP 及其 SSL 功能结合在一起这在 boost 官方网站上没有解释。一切都很好,现在我正处于执行阶段,这是一个令人头疼的问题出现的地方,在我构建请求流后的代码中,我正在使用 boost::asio::async_write 来传递它,在运行时我收到如下错误,我非常确定它是由 boost::asio::async_write 引起的,但我不确定关于导致它这样做的原因,任何人都可以为我提供一些启示,我一直在黑暗中徘徊:((请参阅下面的代码)

terminate called after throwing an instance of 'boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::system::system_error> >'
what(): write: uninitialized

using boost::asio::ip::tcp;
string my_password_callback(size_t, boost::asio::ssl::context_base::password_purpose);
void handle_resolve(const boost::system::error_code& ,
tcp::resolver::iterator);
bool verify_certificate();
void handle_read();
void handle_write();



int i,j,rc;
sqlite3 *db;
string selectsql;
sqlite3_stmt *stmt;
char *zErrMsg = 0;
stringstream ss;
boost::asio::io_service io_service1;
boost::asio::io_service &io_service(io_service1);
boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23);
boost::asio::ssl::context& context_=ctx;
boost::asio::ssl::stream<boost::asio::ip::tcp::socket> socket_(io_service,context_);
int main()
{
boost::shared_ptr<boost::asio::ssl::context>(boost::asio::ssl::context::sslv23);
context_.set_options(boost::asio::ssl::context::default_workarounds| boost::asio::ssl::context::no_sslv2
| boost::asio::ssl::context::single_dh_use);
context_.set_password_callback(my_password_callback);
context_.use_certificate_chain_file("SSL\\test.crt");
context_.use_private_key_file("SSL\\test.key", boost::asio::ssl::context::pem);
tcp::resolver resolver_(io_service);
tcp::resolver::query query("172.198.72.135:3000", "http");
resolver_.async_resolve(query,boost::bind(handle_resolve,
boost::asio::placeholders::error,
boost::asio::placeholders::iterator));
boost::asio::streambuf request;
string path="https://172.198.72.135:3000/journals/enc_data?";
while(true)
{
char * EJTEXT;
int ID;
if(sqlite3_open("c:\\MinGW\\test.db", &db))
{
selectsql="select IEJ,EJ from EJ limit 1";
sqlite3_prepare_v2(db, selectsql.c_str(), -1, &stmt, NULL);
if(sqlite3_step(stmt)==SQLITE_ROW){
ID=sqlite3_column_int(stmt,0);
EJTEXT=(char *)sqlite3_column_text(stmt,1);
}
else{

}
sqlite3_finalize(stmt);
sqlite3_close(db);
}
string EJ=EJTEXT;
E.Encrypt(EJ);
string data=E.Url_safe(E.cipher);--my logic
string Iv=E.Url_safe(E.encoded_iv);--my logic

std::ostream request_stream(&request);
request_stream << "POST " <<path+"Data="+data+"&"+"iv="+Iv;
request_stream << "Host: " <<"172.198.72.135"<< "\r\n";
request_stream << "Accept: */*\r\n";
request_stream << "Connection: close\r\n\r\n";
//try{
boost::asio::async_write(socket_, request,
boost::asio::transfer_at_least(1),
boost::bind(handle_write));
temp="";
data="";
Iv="";

boost::asio::streambuf response;
std::istream response_stream(&response);
std::string http_version;
response_stream >> http_version;
unsigned int status_code;
response_stream >> status_code;
std::string status_message;
std::getline(response_stream, status_message);
if (!response_stream || http_version.substr(0, 5) != "HTTP/")
{
l.HTTP_SSLLOG("Invalid response");
}
if (status_code== 200)
{
string deletesql="delete * from EJ where IEJ="+ID;
if(sqlite3_open("c:\\MinGW\\test.db", &db))
{
rc=sqlite3_exec(db, deletesql.c_str(), 0, 0, &zErrMsg);
sqlite3_close(db);
if(rc)
{
ss<<ID;
l.EJ_Log("ERROR DELETING EJ FOR "+ss.str());
}
}
else{
l.DB_Log("ERROR OPENING DB");
}
}
else{
continue;
}
Sleep(6000);
}
return 0;
}

string my_password_callback(size_t t, boost::asio::ssl::context_base::password_purpose p)//std::size_t max_length,ssl::context::password_purpose purpose )
{
std::string password;
return "balaji";
}

void handle_resolve(const boost::system::error_code& err,
tcp::resolver::iterator endpoint_iterator)
{
if (!err)
{
socket_.set_verify_mode(boost::asio::ssl::verify_peer | boost::asio::ssl::verify_fail_if_no_peer_cert);
socket_.set_verify_callback(boost::bind(verify_certificate));
boost::asio::connect(socket_.lowest_layer(), endpoint_iterator);
}
else
{
l.HTTP_SSLLOG("Error resolve: "+err.message());
}
}

bool verify_certificate()
{
bool preverified =true;
context_.set_default_verify_paths();
return preverified;
}

void handle_read()
{

}
void handle_write()
{
boost::asio::async_read_until(socket_, response, "\r\n",
boost::bind(handle_read));


}

最佳答案

异步操作旨在不抛出异常,而是将错误作为第一个参数 (boost::system::error_code) 传递给完成处理程序。例如下面的程序demonstrates async_write() 因未初始化错误而失败:

#include <iostream>
#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>

int main()
{
boost::asio::io_service io_service;
boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23);
boost::asio::ssl::stream<boost::asio::ip::tcp::socket> socket(io_service, ctx);
boost::asio::async_write(socket, boost::asio::buffer("demo"),
[](const boost::system::error_code& error, std::size_t bytes_transferred)
{
std::cout << error.message() << std::endl;
});
io_service.run();
}

上面的程序会输出uninitialized。如果异步操作抛出异常,则强烈表明正在调用未定义的行为。

根据发布的代码,async_write()操作可能违反调用者保留底层缓冲区内存所有权的要求,调用者必须保证它在调用处理程序之前保持有效。在这种情况下,如果 while 循环的下一次迭代可能会使提供给先前迭代的 async_write() 操作的缓冲区无效。

然而,即使没有未定义的行为,也会有其他问题,因为程序既不尝试建立连接也不执行 SSL 握手,这两者都必须在通过加密连接传输或接收数据之前完成。


当使用异步操作时,作为整个操作流程一部分的 while-sleep 循环通常是代码异味的标志。考虑删除 sqlite3 和加密代码,并首先启动并运行 SSL 原型(prototype)。它也可能有助于在启用最高警告级别/迂腐标志的情况下进行编译。 Boost.Asio SSL overview展示了一个典型的同步使用模式:

using boost::asio::ip::tcp;
namespace ssl = boost::asio::ssl;
typedef ssl::stream<tcp::socket> ssl_socket;

// Create a context that uses the default paths for
// finding CA certificates.
ssl::context ctx(ssl::context::sslv23);
ctx.set_default_verify_paths();

// Open a socket and connect it to the remote host.
boost::asio::io_service io_service;
ssl_socket sock(io_service, ctx);
tcp::resolver resolver(io_service);
tcp::resolver::query query("host.name", "https");
boost::asio::connect(sock.lowest_layer(), resolver.resolve(query));
sock.lowest_layer().set_option(tcp::no_delay(true));

// Perform SSL handshake and verify the remote host's
// certificate.
sock.set_verify_mode(ssl::verify_peer);
sock.set_verify_callback(ssl::rfc2818_verification("host.name"));
sock.handshake(ssl_socket::client);

// ... read and write as normal ...

official SSL example也可以作为使用异步操作的一个很好的起点或引用。确认 SSL 原型(prototype)正常工作后,将 sqlite3 和加密逻辑添加回程序。

此外,如果使用多个线程,请注意 SSL 流不是线程安全的。所有异步操作必须通过显式 strand 同步.对于组合操作,例如 async_write(),启动函数必须在 strand 的上下文中调用,并且完成处理程序必须由相同的 包装链

关于c++ - 写入:执行 boost::asio::async_write 时出现单元化错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32441588/

34 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com