- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我创建了一个程序,该程序利用 boost 的 ssl 实现来使用 async_read_some()
和 async_write_some()
向远程服务器发送和接收小数据包。读取和写入被包裹在一个链中以防止并发读取和写入。此外,我为每个创建的包装函数都包含一个互斥锁,以进一步防止并发访问(可能有点过分,但不会造成伤害)。写入存储在写入队列中,当线程收到数据可用的通知时,写入队列将被发送。
我遇到的问题发生在按顺序执行大量写入时,会导致各种错误,例如 Second Chance Assertion Failed 和 Access Violation。我还收到“解密失败或错误记录 mac”的读取错误。
根据我目前所做的研究,我发现如果同时执行读取和写入,SSL 套接字可能会损坏 - 至少根据讨论 here和 here OP的症状与我的非常相似。他还说他使用的那条线不起作用,但我不明白他的解决方案。这对于我因尝试使用防止并发读写的方法而遇到的问题是有意义的。
我一直在使用的解决方法是限制顺序写入,以便每个写入之间至少有 20 毫秒的间隔。低于这个,我就会开始出错。不过,此解决方法不是很好,因为在某些时候可能仍然存在导致错误的并发读/写。
这是我的读/写代码的摘要:
void client::write(std::string message, char packetType) {
boost::lock_guard<boost::shared_mutex> lock(writeInProgressMutex);
std::string preparedMessage = prepareWrite(message, packetType);
char data_sent[2048];
for(std::string::size_type i = 0; i < preparedMessage.size(); ++i) {
data_sent[i] = preparedMessage[i];
if (i + 1 == preparedMessage.size()) {
data_sent[i+1] = NULL;
}
}
socket_->async_write_some(boost::asio::buffer(data_sent), strand_.wrap(boost::bind(&client::handle_write, this, boost::asio::placeholders::error)));
}
void client::read() {
boost::lock_guard<boost::shared_mutex> lock(readInProgressMutex);
socket_->async_read_some(boost::asio::buffer(data_), strand_.wrap(boost::bind(&client::handle_read, this, boost::asio::placeholders::error)));
}
我试验过不同类型的互斥体,所以我认为这不是问题所在。如果有人知道确保我的链正常工作的方法,或者您可以在我的代码/设计中看到一些明显的错误,请告诉我!
最佳答案
简而言之,验证对 client::write()
和 client::read()
的所有调用都在 strand_
中运行。如果没有额外的代码,同步结构(例如互斥锁)将无法有效地防止并发操作被调用。
ssl::stream
thread safety 的 Boost.Asio 文档强调 strand
要求:
Distinct objects: Safe.
Shared objects: Unsafe. The application must also ensure that all asynchronous operations are performed within the same implicit or explicit strand.
如果 ssl::stream
操作仅在单个线程中调用,那么它是安全的,因为它们在隐式链中运行。另一方面,如果多个线程在 ssl::stream
上调用操作,则它们必须与链显式同步。由于没有引入自定义的中间处理程序,其他同步构造(例如互斥锁)将无效 asio_handler_invoke
功能。
这是一个流程图,显示了异步写入链的必要链用法:
void client::start_write_chain()
{
strand_.post(boost::bind(&client::write, ...)) ---.
} .----------------------------------------------'
| .-------------------------------------------.
V V |
void client::write(...) |
{ |
... |
socket_->async_write_some(buffer, strand_.wrap( |
boost::bind(&client::handle_write, ...))); --. |
} .--------------------------------------------' |
V |
void client::handle_write( |
boost::system::error_code& error, |
std::size_t bytes_transferred) |
{ |
// If there is still data remaining. |
if (bytes_transferred < all_data) |
write(...); -----------------------------------'
}
此要求是 ssl::stream
异步操作根据组合操作实现的实现细节的结果。初始操作可能发生在调用者的上下文中,因此需要从 strand_
中调用 client::write()
。这些组合操作可能会导致对 socket_
的许多中间调用。由于这些中间调用不知道 writeInProgressMutex
,因此互斥体无法有效保护 socket_
。考虑阅读 this有关组合操作和 strands
的更多详细信息,请回答。
此外,在 client::write()
中,缓冲区 data_sent
的生命周期未能满足 ssl::stream::async_write_some()
的要求,其中指出:
Although the buffers object may be copied as necessary, ownership of the underlying buffers is retained by the caller, which must guarantee that they remain valid until the handler is called.
在这种情况下,data_sent
的生命周期在 client::write()
返回时结束,这可能发生在调用完成处理程序之前。
关于c++ - boost::asio::ssl 多线程应用程序访问冲突,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18656919/
关闭。这个问题是opinion-based 。目前不接受答案。 想要改进这个问题吗?更新问题,以便 editing this post 可以用事实和引文来回答它。 . 已关闭 4 年前。 Improv
PowerShell Web Access 允许您通过 Web 浏览器运行 PowerShell cmdlet。它显示了一个基于 Web 的控制台窗口。 有没有办法运行 cmdlet 而无需在控制台窗
我尝试在无需用户登录的情况下访问 Sharepoint 文件。 我可以通过以下任一方式获取访问 token 方法一: var client = new RestClient("https://logi
我目前正在尝试通过 Chrome 扩展程序访问 Google 服务。我的理解是,对于 JS 应用程序,Google 首选的身份验证机制是 OAuth。我的应用目前已成功通过 OAuth 向服务进行身份
假设我有纯抽象类 IHandler 和派生自它的类: class IHandler { public: virtual int process_input(char input) = 0; };
我有一个带有 ThymeLeaf 和 Dojo 的 Spring 应用程序,这给我带来了问题。当我从我的 HTML 文件中引用 CSS 文件时,它们在 Firebug 中显示为中止。但是,当我通过在地
这个问题已经有答案了: JavaScript property access: dot notation vs. brackets? (17 个回答) 已关闭 6 年前。 为什么这不起作用? func
我想将所有流量重定向到 https,只有 robot.txt 应该可以通过 http 访问。 是否可以为 robot.txt 文件创建异常(exception)? 我的 .htaccess 文件: R
我遇到了 LinkedIn OAuth2: "Unable to verify access token" 中描述的相同问题;但是,那里描述的解决方案并不能解决我的问题。 我能够成功请求访问 toke
问题 我有一个暴露给 *:8080 的 Docker 服务容器. 我无法通过 localhost:8080 访问容器. Chrome /curl无限期挂断。 但是如果我使用任何其他本地IP,我就可以访
我正在使用 Google 的 Oauth 2.0 来获取用户的 access_token,但我不知道如何将它与 imaplib 一起使用来访问收件箱。 最佳答案 下面是带有 oauth 2.0 的 I
我正在做 docker 入门指南:https://docs.docker.com/get-started/part3/#recap-and-cheat-sheet-optional docker-co
我正在尝试使用静态 IP 在 AKS 上创建一个 Web 应用程序,自然找到了一个带有 Nginx ingress controller in Azure's documentation 的解决方案。
这是我在名为 foo.js 的文件中的代码。 console.log('module.exports:', module.exports) console.log('module.id:', modu
我试图理解访问键。我读过https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-se
我正在使用 MGTwitterEngine"将 twitter 集成到我的应用程序中。它在 iOS 4.2 上运行良好。当我尝试从任何 iOS 5 设备访问 twitter 时,我遇到了身份验证 to
我试图理解访问键。我读过https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-se
我正在使用以下 API 列出我的 Facebook 好友。 https://graph.facebook.com/me/friends?access_token= ??? 我想知道访问 token 过
401 Unauthorized - Show headers - { "error": { "errors": [ { "domain": "global", "reas
我已经将我的 django 应用程序部署到 heroku 并使用 Amazon s3 存储桶存储静态文件,我发现从 s3 存储桶到 heroku 获取数据没有问题。但是,当我测试查看内容存储位置时,除
我是一名优秀的程序员,十分优秀!