- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
在 boost::asio::async_read_until 之后,我面临周期性的无限等待处理程序调用。这出现在两种情况下:
鉴于不是每次都有,在我看来,我使用 async_read_until、async_write 和 boost::asio::strand 不正确。
这是简化的服务器架构:
(一些发送到服务器的命令不需要响应,有时需要在服务器上发生某些事件后向客户端发送命令,即不从客户端获取数据。值得澄清的是在同一个套接字上永远不要同时运行多个 async_read_until 操作和多个 async_write 操作。)
还有客户的:
服务器代码:
#include <iostream>
#include <istream>
#include <ostream>
#include <string>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/thread.hpp>
class server_session
: public boost::enable_shared_from_this<server_session>
{
public:
server_session(boost::asio::io_service& io_service)
: _io_service(io_service)
, _socket(io_service)
, _strand(io_service)
, _delimiter('\b')
{}
boost::asio::ip::tcp::socket& socket()
{
return _socket;
}
void read()
{
boost::asio::async_read_until(
_socket,
_streambuf,
_delimiter,
_strand.wrap(
boost::bind(
&server_session::handle_read,
shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred
)
)
);
}
void handle_read(const boost::system::error_code& ec, std::size_t bytes_transferred)
{
if (ec)
{
std::cerr << "async_read_until error: " << ec.message() << std::endl;
return;
}
std::istream is(&_streambuf);
std::string msg;
std::getline(is, msg, _delimiter);
read();
_io_service.post(
boost::bind(
&server_session::proc_msg,
shared_from_this(),
msg
)
);
}
void proc_msg(const std::string msg)
{
// command proc here
std::cout << "received: " << msg << std::endl;
static std::uint64_t i = 0;
write("resp_" + std::to_string(i++));
}
void write(const std::string& msg)
{
_strand.post(
boost::bind(
&server_session::write_impl,
shared_from_this(),
boost::shared_ptr<std::string>(new std::string(msg + _delimiter))
)
);
}
private:
void write_impl(const boost::shared_ptr<std::string>& text_ptr)
{
boost::asio::async_write(
_socket,
boost::asio::buffer(text_ptr->data(), text_ptr->size()),
_strand.wrap(
boost::bind(
&server_session::handle_write,
shared_from_this(),
text_ptr,
boost::asio::placeholders::error
)
)
);
}
void handle_write(const boost::shared_ptr<std::string>, const boost::system::error_code& ec)
{
if (ec)
{
std::cerr << "async_write error: " << ec.message() << std::endl;
}
}
boost::asio::io_service& _io_service;
boost::asio::ip::tcp::socket _socket;
boost::asio::strand _strand;
boost::asio::streambuf _streambuf;
char _delimiter;
};
class server
{
public:
server(int port)
: _acceptor(
_io_service,
boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(),port)
)
{
start_accept();
boost::thread_group thd_grp;
for (int i = 0; i < 2; ++i)
{
thd_grp.create_thread(
boost::bind(&boost::asio::io_service::run, &_io_service)
);
}
thd_grp.join_all();
}
private:
void start_accept()
{
_session_ptr.reset(new server_session(_io_service));
_acceptor.async_accept(
_session_ptr->socket(),
boost::bind(
&server::handle_accept,
this,
boost::asio::placeholders::error
)
);
}
void server::handle_accept(const boost::system::error_code& ec)
{
if (ec)
{
std::cerr << "handle_accept error: " << ec.message() << std::endl;
return;
}
_session_ptr->read();
start_accept();
}
boost::asio::io_service _io_service;
boost::asio::ip::tcp::acceptor _acceptor;
boost::shared_ptr<server_session> _session_ptr;
};
int main(int argc, char** argv)
{
if (argc != 2)
{
std::cerr << "usage: " << argv[0] << " <port>";
return EXIT_FAILURE;
}
server s(std::stoi(argv[1]));
return EXIT_SUCCESS;
}
客户代码:
#include <iostream>
#include <istream>
#include <ostream>
#include <string>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
class client
{
public:
client(const std::string& host, const std::string& port)
: _socket(_io_service)
, _resolver(_io_service)
, _query(host, port)
, _delimiter('\b')
{
_iterator = _resolver.resolve(_query);
boost::asio::async_connect(
_socket,
_iterator,
boost::bind(
&client::handle_connect,
this,
boost::asio::placeholders::error
)
);
_io_service.run();
}
void handle_connect(const boost::system::error_code& ec)
{
if (ec)
{
std::cerr << "async_connect error: " << ec.message() << std::endl;
return;
}
write();
}
void write()
{
static std::uint64_t i = 0;
boost::shared_ptr<std::string> msg_ptr(new std::string("req_" + std::to_string(i++) + _delimiter));
boost::asio::async_write(
_socket,
boost::asio::buffer(msg_ptr->data(), msg_ptr->size()),
boost::bind(
&client::handle_write,
this,
msg_ptr,
boost::asio::placeholders::error
)
);
}
void handle_write(const boost::shared_ptr<std::string>, const boost::system::error_code& ec)
{
if (ec)
{
std::cerr << "async_write error: " << ec.message() << std::endl;
return;
}
read();
}
void read()
{
boost::asio::async_read_until(
_socket,
_streambuf,
_delimiter,
boost::bind(
&client::handle_read,
this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred
)
);
}
void handle_read(const boost::system::error_code& ec, std::size_t bytes_transferred)
{
if (ec)
{
std::cerr << "async_read_until error: " << ec.message() << std::endl;
return;
}
std::istream is(&_streambuf);
std::string msg;
std::getline(is, msg, _delimiter);
std::cout << "received: " << msg << std::endl;
write();
}
boost::asio::io_service _io_service;
boost::asio::ip::tcp::socket _socket;
boost::asio::ip::tcp::resolver _resolver;
boost::asio::ip::tcp::resolver::query _query;
boost::asio::ip::tcp::resolver::iterator _iterator;
boost::asio::streambuf _streambuf;
char _delimiter;
};
int main(int argc, char** argv)
{
if (argc != 3)
{
std::cerr << "usage: " << argv[0] << " <host> <port>";
return EXIT_FAILURE;
}
client c(argv[1], argv[2]);
return EXIT_SUCCESS;
}
当 socket 上的 async_read_until 已经运行,而 strand 被使用时,async_write 是否正确?
async_read_until 是否有可能以某种方式在内部阻塞套接字,事实上,数据没有发送到客户端?
对于代码可能无法正常工作的任何建议,我将不胜感激
我使用的是 boost 1.58,平台 - Win7 和 Win8。在本地主机和 LAN 上测试,结果如上。
最佳答案
我可以告诉您至少您应该使用 asio::deadline_timer 并在每次开始新的异步操作时重置计时器。您尤其应该使用 async_read_until 之类的操作来执行此操作,因为您正在指定可能永远不会满足的调用完成条件。查看 deadline_timer 示例并在每个异步操作上实现 async_wait,指定该操作的截止日期。在超时操作中,您可以根据需要取消挂起的异步操作、出错或重新启动。
关于c++ - 无限执行boost asio async_read_until,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31063050/
我正在尝试使用 boost asio 库来实现网络编程。这是当一些数据(以“##”结尾)到达端点时调用的代码。 { boost::asio::async_read_until(m_socket
我在此处记录的函数中实现第三个参数时遇到问题: http://www.boost.org/doc/libs/1_39_0/doc/html/boost_asio/reference/async_rea
我在使用 async_read_until 时遇到问题。我最初使用的是 async_receive,但我的服务器的响应增长到不止一个数据包,我遇到了一个问题,即 async_receive 在收到第一
我正在尝试使用 boost::shared_ptr与 async_read_until并且无法让它工作。这是我的简化代码: 标题 boost::asio::io_service io_service;
我正在使用带有 '\n' 分隔符的 asio::async_read_until 来支持从服务器获取字符数据的 TCP 客户端。此服务器不断发送 '\n' 终止行;准确地说,它可以同时写入单行或多行的
在 boost::asio::async_read_until 之后,我面临周期性的无限等待处理程序调用。这出现在两种情况下: 在服务器上,尽管客户端 boost::asio::async_write
我正在尝试将 c++11 lambda 与 boost::asio::async_read_until 一起使用,如下所示: void TCPSession::readData() { auto
我正在尝试使用自定义匹配函数作为 boost::asio 组合操作的一部分。当传入 std::move(*this) 作为异步操作的处理程序时,VS2017 无法使用自定义匹配条件推断参数。 组合操作
我想知道如何限制使用 async_read_until 读取的字节大小。从现在开始,我将它与定界符字符一起使用,但我想更改。这是我所做的: void Client::doRead()
我正在学习如何将 Boost:asio 库与串行端口一起使用。我使用同步写入和读取编写了一些代码,现在我想使用异步,但它不起作用。简单示例: void readHandler(const boost:
我正在尝试修改来自 boost asio 的 echo 服务器示例,当我尝试使用 boost::asio::async_read_until 时遇到了问题。这是代码: #include #i
我遇到了一个不寻常的问题。我有一个 C++ Boost.ASIO 网络服务器,为了处理传入的请求,我正在使用以下代码: boost::asio::async_read_until( socke
我有一个关于使用 boost asio 的 async_read_until 的一般性问题。文档说调用处理程序时缓冲区内可能有更多数据。有没有什么办法可以解决这个问题,并在序列条件匹配后立即阻止缓冲区
我正在尝试在本地网络上的两台计算机之间建立连接,一台使用 Boost Asio C++ TCP 异步服务器示例的略微修改版本,另一台使用 NodeJS。 tcp_client.js : var net
我正在从串行设备读取,其中必须特别请求每条消息。例如。您发送请求并获得带有序列化负载的响应。 每条消息按顺序包含这些部分: 序言(2 字节,“$M”) HEADER(3字节,包含有效载荷长度N) 有效
有没有办法结合两个条件读取,直到找到匹配字符或收到 128 个字节? 可以限制 streambuf 的大小: inBuf = std::make_shared(limit_size); 但是当处理程序
我正在使用以下方法: boost::asio::streambuf io_bufstream; boost::asio::async_read_until(socket_, io_bufstream,
我正在用 boost asio 制作一个 Irc 机器人,我在编译它时遇到了一些问题,而且错误不是真正可读的。 似乎其中一个async_read_until进行得不是很好,但我不知道为什么。 这是 g
我使用了来自 boost 的异步 tcp 服务器示例,它与我的应用程序正在做的很接近。下面的代码示例是一个完整的示例。 首先,我开始异步读取操作,直到分隔符 char。在这种情况下,它是 http h
我正在修改 Boost Asio 回显示例以使用 async_read_until 逐字读取输入。即使我使用 async_read_until,所有发送的数据似乎都是从套接字读取的。有人可以建议: #
我是一名优秀的程序员,十分优秀!