Boost (Beast) websocket:同步写入挂起
Boost (Beast) websocket: synchronous write hangs
我遇到了boost beast websocket流的问题。当我尝试写入远程终结点已停止响应的流时,会间歇性地发生此问题(特别是由于远程与网络物理断开连接(。
发生此问题时,同步 stream.write(( 调用最终挂起很长时间 (分钟( 直到套接字最终关闭。我知道这种行为可能是因为我的程序在没有来自远程的确认的情况下继续写入流,直到发送缓冲区已满。我想知道是否有办法将超时应用于写入调用,或者是否有一个更类似于 stream.try_write(( 的接口,我可以在其中将错误处理提升到用户级别。
我确实意识到一种选择是使用async_write界面。但是,我担心这会通过将套接字写入操作推迟到下一次io_context迭代来对我的发送性能产生负面影响。
下面是调用挂起时线程的堆栈跟踪。
#0 0x00007f468cf33624 in poll () from /lib64/libc.so.6
#1 0x000000000043e5a7 in boost::asio::detail::socket_ops::poll_write (ec=..., msec=-1, state=0 ' 00', s=16)
at /usr/include/boost/asio/detail/impl/socket_ops.ipp:1898
#2 boost::asio::detail::socket_ops::sync_send (ec=..., all_empty=<optimized out>, flags=0, count=<optimized out>, bufs=0x7fff43c17e20,
state=<optimized out>, s=<optimized out>) at /usr/include/boost/asio/detail/impl/socket_ops.ipp:1224
#3 boost::asio::detail::reactive_socket_service_base::send<boost::asio::detail::prepared_buffers<boost::asio::const_buffer, 64ul> > (impl=...,
buffers=..., ec=..., this=<optimized out>, flags=0) at /usr/include/boost/asio/detail/reactive_socket_service_base.hpp:245
#4 0x0000000000481c71 in boost::asio::basic_stream_socket<boost::asio::ip::tcp>::write_some<boost::asio::detail::prepared_buffers<boost::asio::const_buffer, 64ul> > (ec=..., buffers=..., this=0x108ad50) at /usr/include/boost/asio/buffer.hpp:941
#5 boost::asio::detail::write_buffer_sequence<boost::asio::basic_stream_socket<boost::asio::ip::tcp>, boost::beast::buffers_cat_view<boost::asio::mutable_buffer, boost::beast::buffers_prefix_view<boost::beast::buffers_suffix<boost::beast::basic_multi_buffer<std::allocator<char> >::const_buffers_type> > >, boost::beast::buffers_cat_view<boost::asio::mutable_buffer, boost::beast::buffers_prefix_view<boost::beast::buffers_suffix<boost::beast::basic_multi_buffer<std::allocator<char> >::const_buffers_type> > >::const_iterator, boost::asio::detail::transfer_all_t> (completion_condition=..., ec=..., buffers=..., s=...)
at /usr/include/boost/asio/impl/write.hpp:53
#6 boost::asio::write<boost::asio::basic_stream_socket<boost::asio::ip::tcp>, boost::beast::buffers_cat_view<boost::asio::mutable_buffer, boost::beast::buffers_prefix_view<boost::beast::buffers_suffix<boost::beast::basic_multi_buffer<std::allocator<char> >::const_buffers_type> > >, boost::asio::detail::transfer_all_t> (ec=..., buffers=..., s=..., completion_condition=...) at /usr/include/boost/asio/impl/write.hpp:69
#7 boost::asio::write<boost::asio::basic_stream_socket<boost::asio::ip::tcp>, boost::beast::buffers_cat_view<boost::asio::mutable_buffer, boost::beast::buffers_prefix_view<boost::beast::buffers_suffix<boost::beast::basic_multi_buffer<std::allocator<char> >::const_buffers_type> > > > (ec=..., buffers=..., s=...)
at /usr/include/boost/asio/impl/write.hpp:92
#8 boost::beast::websocket::stream<boost::asio::basic_stream_socket<boost::asio::ip::tcp> >::write_some<boost::beast::basic_multi_buffer<std::allocator<char> >::const_buffers_type> (this=this@entry=0x108ad50, fin=fin@entry=true, buffers=..., ec=...) at /usr/include/boost/beast/websocket/impl/write.ipp:625
#9 0x000000000042c5e1 in boost::beast::websocket::stream<boost::asio::basic_stream_socket<boost::asio::ip::tcp> >::write<boost::beast::basic_multi_buffer<std::allocator<char> >::const_buffers_type> (ec=..., buffers=..., this=0x108ad50)
Beast websockets 不支持非阻塞模式。在某些情况下,如果在与 websocket 流一起使用的套接字上设置此模式,则websocket::stream
的实现将产生未定义的行为。缺少超时是同步代码的普遍问题。除了使用异步操作之外,您真的别无选择。您说要直接从堆栈发送缓冲区,这在使用协程在异步上下文中很容易完成(请参阅boost::asio::spawn
和boost::asio::yield_context
(。
有许多技术允许异步 I/O 执行与同步 I/O 相同或更好的性能,包括低所需延迟的情况。
以下是Boost.Asio作者直接提供的关于实现超低延迟的建议: https://groups.google.com/a/isocpp.org/d/msg/sg14/FoLFHXqZSck/i4rdO-O3BQAJ
我能够通过将底层流套接字置于非阻塞模式来解决此问题:
socket.non_blocking(true);
在此模式下,一旦发送缓冲区已满,write()
调用将立即返回boost::system::error_code::try_again
(也称为 posixEAGAIN
(。
- 挂起和取消挂起一个文件DLL
- 如何防止C++遗留代码中的挂起指针
- 为什么所有C++编译器都会崩溃或挂起此代码
- 我编写了代码将十进制分数转换为其二进制等效数.它编译得很好,但在执行时挂起
- 构建挂起,即使是适度的文件大小
- 循环挂起迭代的 std::擦除 on std::list
- Poco::Net::FTPClientSession 在 open() 方法上挂起 129 秒,如果 ftp 主机不存
- Node.js fs.open() 在尝试打开 4 个以上的命名管道 (FIFO) 后挂起
- 从不同进程中的另一个线程挂起/恢复线程或进程
- Boost (Beast) websocket:同步写入挂起
- 为什么析构函数挂起
- 使用互斥会挂起程序
- 在C++和 Python 程序中使用命名管道的 IPC 挂起
- 设置变量时C++程序挂起
- 第一次尝试使用new动态创建结构数组,程序挂起没有错误
- 从stdin读取时子进程挂起(fork/dup2竞争条件)
- 有时ShowWindow从不调用OnShowWindow,主应用程序挂起
- 如何防止GUI挂起,同时允许第二次操作与Qt中的第一次操作一起执行
- WTSFreeMemory在启动期间从服务调用时挂起-我应该省略吗
- 带有互锁操作的线程同步在Visual Studio 2013 c++原生代码中挂起