- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我编写了以下类通过 ssl 连接将数据发送到服务器。数据打包在 protobuf 消息中。当仅发送和接收一条消息(如获取和发送心跳)时,它可以完美地工作。但是当涉及到发送多个消息如心跳和另一个数据请求消息时,由于管道损坏而失败。
示例代码:
SSLHandler conn;//working
while(true){
std::vector<char> msg = buildHearbeatMsg()
conn.writeMessage(msg);
//conn.handleReadMessage(...) get called
}
SSLHandler conn;//broken pipe
while(true){
std::vector<char> msg = buildHearbeatMsg()
conn.writeMessage(msg);
std::vector<char> msg2 = buildRequestDataMsg()
conn.write(msg);//broken pipe
}
类是
#ifndef SSLHANDLER_H
#define SSLHANDLER_H
#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>
#include <boost/bind.hpp>
#include <iostream>
#include <istream>
#include <ostream>
#include <string>
#include <boost/lockfree/spsc_queue.hpp>
#include "msg.pb.h"
const int READ_SIZE =0;
const int READ_MSG=1;
class SSLHandler
{
public:
SSLHandler(boost::asio::io_service& io_service, boost::asio::ssl::context& context, boost::asio::ip::tcp::resolver::iterator endpoint_iterator)
: socket_(io_service, context) , mEndpointIterator (endpoint_iterator)
{
socket_.set_verify_mode(boost::asio::ssl::context::verify_none);
socket_.set_verify_callback(boost::bind(&SSLHandler::verify_certificate, this, _1, _2));
mode = READ_SIZE;
}
bool verify_certificate(bool preverified, boost::asio::ssl::verify_context& ctx);
void handle_connect(const boost::system::error_code& error);
void handle_handshake(const boost::system::error_code& error);
void handle_write(const boost::system::error_code& error, size_t bytes_transferred);
void handle_read(const boost::system::error_code& error, size_t bytes_transferred);
void handle_read_message(const boost::system::error_code& error, size_t bytes_transferred);
void connectToServer();
void writeMessage(std::vector<char> &array);
void setRequestMsg(std::vector<char> &&array);
private:
boost::asio::ssl::stream<boost::asio::ip::tcp::socket> socket_;
boost::asio::ip::tcp::resolver::iterator mEndpointIterator;
char reply_[0x1 << 16]; //=65356 bytes
int mode;
uint32_t size;
std::vector<char> requestMsg;
std::vector<char> replyMsg;
};
#endif // SSLHANDLER_H
#include "sslhandler.h"
bool SSLHandler::verify_certificate(bool preverified, boost::asio::ssl::verify_context &ctx)
{
char subject_name[256];
X509* cert = X509_STORE_CTX_get_current_cert(ctx.native_handle());
X509_NAME_oneline(X509_get_subject_name(cert), subject_name, 256);
std::cout << "Verifying:\n" << subject_name << std::endl;
return preverified;
}
void SSLHandler::handle_connect(const boost::system::error_code &error)
{
if(!error){
std::cout << "Connection OK!" << std::endl;
socket_.async_handshake(boost::asio::ssl::stream_base::client, boost::bind(&SSLHandler::handle_handshake, this, boost::asio::placeholders::error));
}else{
std::cout << "Connect failed: " << error.message() << std::endl;
}
}
void SSLHandler::handle_handshake(const boost::system::error_code &error)
{
if(!error){
std::cout << "Sending request: " << std::endl;
boost::asio::async_write(socket_,
boost::asio::buffer(requestMsg.data(), requestMsg.size()),
boost::bind(&SSLHandler::handle_write, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}else{
std::cout << "Handshake failed: " << error.message() << std::endl;
}
}
void SSLHandler::handle_write(const boost::system::error_code &error, size_t bytes_transferred)
{
if (!error){
if(mode==READ_SIZE){
std::cout << "Sending request OK!" << std::endl;
// char respond[bytes_transferred] = "";
boost::asio::async_read(socket_, boost::asio::buffer(reply_,4),
boost::bind(&SSLHandler::handle_read,
this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
std::cerr << "respond is " ;
}
else if(mode == READ_MSG){
std::cout << "Sending request OK!" << std::endl;
// char respond[bytes_transferred] = "";
boost::asio::async_read(socket_, boost::asio::buffer(reply_,size),
boost::bind(&SSLHandler::handle_read_message,
this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
std::cerr << "respond is " ;
}
}else{
std::cout << "Write failed: " << error.message() << std::endl;
}
}
void SSLHandler::handle_read(const boost::system::error_code &error, size_t bytes_transferred)
{
if (!error){
std::cout << "Reply: ";
std::cout.write(reply_, bytes_transferred);
std::cout << "\n";
char sizeLittleEndian[4];
sizeLittleEndian[3] = reply_[0];
sizeLittleEndian[2] = reply_[1];
sizeLittleEndian[1] = reply_[2];
sizeLittleEndian[0] = reply_[3];
memcpy(&size, sizeLittleEndian,sizeof(uint32_t));
std::cerr << "size of msg is " << size;
boost::asio::async_read(socket_, boost::asio::buffer(reply_,size),
boost::bind(&SSLHandler::handle_read_message,
this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
mode = READ_MSG;
}else{
std::cout << "Read failed: " << error.message() << std::endl;
}
}
void SSLHandler::handle_read_message(const boost::system::error_code &error, size_t bytes_transferred)
{
if (!error){
std::cout << "Reply: ";
std::cout.write(reply_, bytes_transferred);
std::cout << "\n";
replyMsg.assign(reply_,reply_+ size);
mpConnector->setReadMsg(replyMsg);// upper get
mode = READ_SIZE;
}else{
std::cout << "Read failed: " << error.message() << std::endl;
}
}
void SSLHandler::connectToServer()
{
boost::asio::async_connect(socket_.lowest_layer(), mEndpointIterator, boost::bind(&SSLHandler::handle_connect, this, boost::asio::placeholders::error));
}
void SSLHandler::writeMessage(std::vector<char> &array)
{
boost::asio::async_write(socket_,
boost::asio::buffer(array.data(), array.size()),
boost::bind(&SSLHandler::handle_write, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
void SSLHandler::setRequestMsg(std::vector<char> &&array)
{
requestMsg = std::move(array);
}
最佳答案
查看关于async_write
的引用资料
The function call always returns immediately
所以如果你有代码
void foo (vector<> data) {
socket.async_write(); // this function returns immediately
}
如果您在同一个套接字上调用多个 foo
函数,您可能会遇到麻烦,因为
The program must ensure that the stream performs no other write operations (such as async_write, the stream's async_write_some function, or any other composed operations that perform writes) until this operation completes.
在您的代码中,您在同一连接对象上调用了 SSLHandler
的多个 writeMessage
方法,这是不正确的方法。
还有第二个问题。您必须确保要使用 async_write
通过套接字发送的数据在 async_write
结束之前仍然存在。此代码使用 async_write
while(true){
std::vector<char> msg = buildHearbeatMsg()
conn.writeMessage(msg);
}
您在 while 范围内创建了 msg
作为局部变量,然后您调用了 writeMessage
但此函数立即返回并且 msg
可以在 async_write
结束工作。
也许您应该使用同步操作而不是异步操作来完成您的任务。
关于c++ - 由于管道损坏,Boost asio 发送消息失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48574602/
使用 asio 库,我想为 asio::serial_port 读/写调用使用超时。 是否可以使用相同的 asio::serial_port asio::io_context 和用于 asio 的相同
对于我正在从事的副业项目应该使用哪种类型的解析器,我有点困惑。我在 asio 文档中找不到答案。 我知道 DNS 可以与 UDP 或 TCP 一起使用,并且通常通过 TCP 发送较大的响应。 asio
在仅从一个线程调用 io_service::run() 的情况下,从不同线程调用 async_write 和 async_read 是否安全?谢谢! 最佳答案 Is it safe to call a
我想知道Boost ASIO 有多受欢迎。它是否被用于任何流行的网络密集型软件中? 最佳答案 用于管理 IBM Blue Gene/Q 的系统软件 super 计算机广泛使用Boost.Asio。
我想使用一个函数来读取套接字端口,并在收到 IP 数据包时交还控制权。 boost::asio::ip::udp::socket 有一个函数接收(或 async_receive),它返回读取了多少字节
我试图调整 Boost 文档中的 SSL 服务器示例 here但我想制作一个应用程序,您可以在其中使用普通 boost::asio::ip::tcp::socket或 SSL 套接字,但我还没有找到将
在查看 boost asio co_spawn 文档 ( https://www.boost.org/doc/libs/1_78_0/doc/html/boost_asio/reference/co_
我正在尝试使用 Boost.ASIO 库,但我找不到如何列出 boost 的可用端口(带有串行端口服务)或套接字(带有网络服务)。 你知道这是否可能吗? 谢谢你。 最佳答案 Boost.Asio 不提
我想使用boost::asio从多个stdout中同时读取stderr和boost::process。但是,我在使用boost::asio时遇到了编译问题,可以重建以下无法编译的最小示例: #incl
提前为一个愚蠢的问题道歉 - 我对这一切都很陌生。 所以我从 here 下载了 asio ,并尝试#include asio.hpp,但出现以下错误; fatal error: boost/confi
我是使用 boost 的项目的一部分作为一个 C++ 库。现在我们要使用 SMTP/POP3/SSL/HTTP/HTTPS。我在 Poco::Net 中检测到几个拟合类和函数 Poco::Net::P
有谁知道有任何实现 Web Sockets 的尝试吗?使用 Boost asio 的 API? 最佳答案 我意识到这是一个旧线程,但想更新以帮助那些寻找答案的人:WebSocket++完全符合要求。
和 asio::thread_pool 有什么区别和一个 asio::io_context谁的run()函数是从多个线程调用的?我可以更换我的 boost::thread_group调用 io_con
我想连接到由目标 IP 地址和端口号指定的服务器套接字。 boost::asio::connect 似乎不允许使用它。我有 ip 目的地作为无符号 int 值。 更新:我能够做到 ba::ip::tc
我在 pc 上有 3 个网络接口(interface),并且想确保当我进行 udp 套接字发送时,它通过特定的网络接口(interface)发送(我有发送数据时使用的 ip 地址)。 这是代码。 ud
我正在使用 ASIO 开发网络应用程序并提到了Chat-Server/Client 我问过类似的问题Here 为了更好地解释,我在这里添加了更多代码: 我的 Cserver Class class C
我已经阅读了 boost asio 引用资料,浏览了教程并查看了一些示例。尽管如此,我还是看不出应该如何拆除套接字: 我应该调用 close() 还是由套接字的析构函数完成? 什么时候应该调用 shu
我认为标题已经说明了大部分内容,但我也有兴趣了解在没有现有解决方案的情况下如何将 DTLS 支持引入 asio 最佳答案 ASIO 本身不支持DTLS 但有一个GitHub 库asio_dtls已向
我正在将 async_read 与 streambuf 一起使用。但是,我想将读取的数据量限制为 4,这样我就可以在进入正文之前正确处理 header 。 我如何使用 async_read 做到这一点
从this example开始,我想用 async_read_until() 替换 async_read()。 所以我查了一下this example ,并查看了如何调用 async_read_unt
我是一名优秀的程序员,十分优秀!