提升 ASIO SSL 写入部分数据

boost asio ssl writing part of data

本文关键字:数据 入部 ASIO SSL 提升      更新时间:2023-10-16

我的客户端-服务器应用程序,通过boost asio进行通信,usign功能:

当连接开始时,客户端向服务器发送一堆请求,服务器发回一些响应。 将asio::ssl添加到项目后,我遇到了以下问题。

有时,服务器只读取请求的第一个固定部分,这是 1/5 次。当客户端断开连接时,服务器将获取所有错过的请求。

在客户端,一切似乎都很好,调用的 callbakcs 没有错误,写入大小是正确的。但是数据包嗅探器的结果显示客户端不发送这部分请求。

客户:

每个"帧"的大小位于标题中,首先必须至少读取标题。 线程工作线程用于后台工作,并将准备好的数据包推送到存储。

using SSLSocket = boost::asio::ssl::stream<boost::asio::ip::tcp::socket>;

class AsyncStrategy :
public NetworkStrategy
{
// other data...
void _WriteHandler(const boost::system::error_code& err, size_t bytes);
bool Connect(const boost::asio::ip::tcp::endpoint& endpoint);
void _BindMessage();
void _BindMessageRemainder(size_t size);
void _AcceptMessage(const boost::system::error_code& err_code, size_t bytes);
void _AcceptMessageRemainder(const boost::system::error_code& err_code, size_t bytes);
// to keep io_service running
void _BindTimer();
void _DumpTimer(const boost::system::error_code& error);
void _SolveProblem(const boost::system::error_code& err_code);
void _Disconnect();
bool verify_certificate(bool preverified,
boost::asio::ssl::verify_context& ctx);
PacketQuery query;
boost::array <Byte, PacketMaxSize> WriteBuff;
boost::array <Byte, PacketMaxSize> ReadBuff;
boost::asio::ip::tcp::endpoint ep;
boost::asio::io_service service;
boost::asio::deadline_timer _Timer{ service };
boost::asio::ssl::context _SSLContext;
SSLSocket sock;
boost::thread Worker;
bool _ThreadWorking;
bool _Connected = false;
};

AsyncStrategy::AsyncStrategy( MessengerAPI& api)
: API{api},_SSLContext{service,boost::asio::ssl::context::sslv23 },
sock{ service,_SSLContext }, _Timer{service},
Worker{ [&]() {
_BindTimer();
service.run();
} },  
_ThreadWorking{ true }
{
_SSLContext.set_verify_mode(boost::asio::ssl::verify_peer);
_SSLContext.set_verify_callback(
boost::bind(&AsyncStrategy::verify_certificate, this, _1, _2));
_SSLContext.load_verify_file("ca.pem");
}

bool AsyncStrategy::verify_certificate(bool preverified,
boost::asio::ssl::verify_context& ctx)
{
return preverified;
}
void AsyncStrategy::_BindMessage()
{
boost::asio::async_read(sock, buffer(ReadBuff,BaseHeader::HeaderSize()),
boost::bind(&AsyncStrategy::_AcceptMessage, this, _1, _2));
}
bool AsyncStrategy::Connect(const boost::asio::ip::tcp::endpoint& endpoint)
{
ep = endpoint;
boost::system::error_code err;
sock.lowest_layer().connect(ep, err);
if (err)
throw __ConnectionRefused{};
// need blocking handshake
sock.handshake(boost::asio::ssl::stream_base::client, err);
if (err)
throw __ConnectionRefused{};
_BindMessage();
return true;
}

void AsyncStrategy::_AcceptMessage(const boost::system::error_code& err_code, size_t bytes)
{
// checking header, to see, packet ends or not
// if there is more data in packet, read rest my binding function
// pseudocode
if( need_load_more )
_BindMessageRemainder(BytesToReceive(FrameSize));
return;
}
// if not use this bind this function next time
_CheckPacket(ReadBuff.c_array(), bytes);
_BindMessage();
}
void AsyncStrategy::_AcceptMessageRemainder(const boost::system::error_code& err_code, size_t bytes)
{
if (err_code)
{
_SolveProblem(err_code);
return;
}
_CheckPacket(ReadBuff.c_array(), bytes + BaseHeader::HeaderSize()); 
_BindMessage();
}
bool AsyncStrategy::Send(const TransferredData& Data)
{
// alreay known, that that data fits in buffer
Data.ToBuffer(WriteBuff.c_array()); 
boost::asio::async_write(sock,
buffer(WriteBuff, Data.NeededSize()),
boost::bind(&AsyncStrategy::_WriteHandler, this, _1, _2));
return true;
}
void AsyncStrategy::_WriteHandler(const boost::system::error_code& err, size_t bytes)
{  
if (err)
_SolveProblem(err);
}

删除所有ssl内容后,数据传输是正常的。正如我所提到的,在SSL集成之前一切正常。

寻找解决方案,我发现如果延迟发送,尝试200毫秒,所有数据传输正常。

Win10, boost 1.60, OpenSSL 1.0.2n

我想我的代码中可能存在错误,但我几乎尝试了我认为的所有内容。寻求建议。

我们看不出Send实际上是如何称呼的。

也许它需要同步。

我们可以让它每次都重用相同的缓冲区,因此重叠的两次写入将破坏该缓冲区。

我们还可以看到,您没有验证Data参数的大小是否适合PacketMaxSize缓冲区。

这意味着如果超过预期的缓冲区大小,您不仅会丢失数据,而且还会调用未定义的行为