执行boost::asio::async_write时错误
Write:Unitialized Error when performing boost::asio::async_write
我已经分配使用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"<< "rn";
request_stream << "Accept: */*rn";
request_stream << "Connection: closernrn";
//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, "rn",
boost::bind(handle_read));
}
异步操作被设计成不抛出异常,而是将错误传递给完成处理程序作为它们的第一个参数(boost::system::error_code
)。例如,下面的程序演示了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原型。它还可以帮助编译启用最高警告级别/迂腐标志。的提振。Asio SSL概述显示了一个典型的同步使用模式:
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 ...
官方SSL示例也可以作为使用异步操作的一个很好的起点或参考。一旦确认SSL原型可以正常工作,然后将sqlite3和加密逻辑添加回程序中。
另外,在使用多个线程的情况下,要注意SSL流不是线程安全的。所有异步操作必须通过显式链进行同步。对于组合操作,例如async_write()
,必须在strand
的上下文中调用初始化函数,并且完成处理程序必须由相同的strand
包装。
- 警告处理为错误这里有什么问题
- "error: no matching function for call to"构造函数错误
- boost::进程间消息队列引发错误
- C++,OpenCV,尝试显示图像时"OpenCV(4.3.0) Error: Assertion failed (size.width>0 && size.height>0)"此错误
- 有关插入适配器的错误。[错误]请求从 'back_insert_iterator<vector<>>' 类型转换为非标量类型
- QT在错误的班级中寻找空位
- vector.resize()中的分配错误
- 代码在main()中运行,但在函数中出现错误
- 释放错误后堆使用
- (C++)分析树以计算返回错误值的简单算术表达式
- Project Euler问题4的错误解决方案
- 我的字符计数代码计算错误.为什么
- 从"int*"强制转换为"unsigned int"会丢失精度错误
- 尝试链接我的着色器时,我收到错误代码"error c5145 must write to gl_position"
- 当客户端在 write() 期间终止连接时,由对等套接字错误重置连接
- 当发生错误(拒绝访问)时调用Curl-headerfunction和write函数
- C++ DLL 到 C# 错误:"Attempted to read or write protected memory. This is often an indication that other
- OpenGL 3.3/GLSL & C++ 错误:"must write to gl_Position"
- ::write()和::read()没有被声明为错误.Qt5 UNIX信号处理
- 等效于 VB DLL 函数声明的 C# 返回并返回'Attempted to read or write protected memory'错误