boost::asio::async_receive 套接字中有 0 个字节
boost::asio::async_receive and 0 bytes in socket
伪代码
boost::asio::streambuf my_buffer;
boost::asio::ip::tcp::socket my_socket;
auto read_handler = [this](const boost::system::error_code& ec, size_t bytes_transferred) {
// my logic
};
my_socket.async_receive(my_buffer.prepare(512),
read_handler);
当使用传统的 recv
和非阻塞套接字时,它 returns -1 当没有任何东西可以从套接字读取时。
但是使用async_receive
如果没有数据就不会调用read_handler
,无限等待
如何实现这样一个逻辑(异步)调用read_handler
和bytes_transferred == 0
(可能设置了错误代码)当没有任何东西可以从套接字读取时?
(async_read_some
具有相同的行为)。
总之,发起async_receive()
操作后,立即取消。如果以 boost::asio::error::operation_aborted
作为错误调用完成处理程序,则操作将被阻止。否则,读取操作成功完成并已从套接字读取或由于其他原因失败,例如远程对等方关闭连接。
socket.async_receive(boost::asio::buffer(buffer), handler);
socket.cancel();
在异步操作的启动函数中,将尝试进行非阻塞读取。 async_receive()
文档中记录了此行为的微妙之处:
Regardless of whether the asynchronous operation completes immediately or not, [...]
因此,如果操作立即完成并成功或出错,则完成处理程序将准备好调用并且不可取消。另一方面,如果操作会阻塞,那么它将被排入反应器进行监控,在那里它变得可取消。
通过在套接字上启用 non-blocking 模式,也可以获得与同步操作类似的行为。当套接字设置为非阻塞时,将阻塞的同步操作将失败并返回 boost::asio::error::would_block
.
socket.non_blocking(true);
auto bytes_transferred = socket.receive(
boost::asio::buffer(buffer), 0 /* flags */, error);
这是一个完整的例子demonstrating这些行为:
#include <array>
#include <iostream>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
// This example is not interested in the handlers, so provide a noop function
// that will be passed to bind to meet the handler concept requirements.
void noop() {}
void print_status(
const boost::system::error_code& error,
std::size_t bytes_transferred)
{
std::cout << "error = (" << error << ") " << error.message() << "; "
"bytes_transferred = " << bytes_transferred
<< std::endl;
}
int main()
{
using boost::asio::ip::tcp;
// Create all I/O objects.
boost::asio::io_service io_service;
tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), 0));
tcp::socket socket1(io_service);
tcp::socket socket2(io_service);
// Connect the sockets.
acceptor.async_accept(socket1, boost::bind(&noop));
socket2.async_connect(acceptor.local_endpoint(), boost::bind(&noop));
io_service.run();
io_service.reset();
std::array<char, 512> buffer;
// Scenario: async_receive when socket has no data.
// Within the intiating asynchronous read function, an attempt to read
// data will be made. If it fails, it will be added to the reactor,
// for monitoring where it can be cancelled.
{
std::cout << "Scenario: async_receive when socket has no data"
<< std::endl;
socket1.async_receive(boost::asio::buffer(buffer), &print_status);
socket1.cancel();
io_service.run();
io_service.reset();
}
// Scenario: async_receive when socket has data.
// The operation will complete within the initiating function, and is
// not available for cancellation.
{
std::cout << "Scenario: async_receive when socket has data" << std::endl;
boost::asio::write(socket2, boost::asio::buffer("hello"));
socket1.async_receive(boost::asio::buffer(buffer), &print_status);
socket1.cancel();
io_service.run();
}
// One can also get the same behavior with synchronous operations by
// enabling non_blocking mode.
boost::system::error_code error;
std::size_t bytes_transferred = 0;
socket1.non_blocking(true);
// Scenario: non-blocking synchronous read when socket has no data.
{
std::cout << "Scenario: non-blocking synchronous read when socket"
" has no data." << std::endl;
bytes_transferred = socket1.receive(
boost::asio::buffer(buffer), 0 /* flags */, error);
assert(error == boost::asio::error::would_block);
print_status(error, bytes_transferred);
}
// Scenario: non-blocking synchronous read when socket has data.
{
std::cout << "Scenario: non-blocking synchronous read when socket"
" has data." << std::endl;
boost::asio::write(socket2, boost::asio::buffer("hello"));
bytes_transferred = socket1.receive(
boost::asio::buffer(buffer), 0 /* flags */, error);
print_status(error, bytes_transferred);
}
}
输出:
Scenario: async_receive when socket has no data
error = (system:125) Operation canceled; bytes_transferred = 0
Scenario: async_receive when socket has data
error = (system:0) Success; bytes_transferred = 6
Scenario: non-blocking synchronous read when socket has no data.
error = (system:11) Resource temporarily unavailable; bytes_transferred = 0
Scenario: non-blocking synchronous read when socket has no data.
error = (system:0) Success; bytes_transferred = 6
伪代码
boost::asio::streambuf my_buffer;
boost::asio::ip::tcp::socket my_socket;
auto read_handler = [this](const boost::system::error_code& ec, size_t bytes_transferred) {
// my logic
};
my_socket.async_receive(my_buffer.prepare(512),
read_handler);
当使用传统的 recv
和非阻塞套接字时,它 returns -1 当没有任何东西可以从套接字读取时。
但是使用async_receive
如果没有数据就不会调用read_handler
,无限等待
如何实现这样一个逻辑(异步)调用read_handler
和bytes_transferred == 0
(可能设置了错误代码)当没有任何东西可以从套接字读取时?
(async_read_some
具有相同的行为)。
总之,发起async_receive()
操作后,立即取消。如果以 boost::asio::error::operation_aborted
作为错误调用完成处理程序,则操作将被阻止。否则,读取操作成功完成并已从套接字读取或由于其他原因失败,例如远程对等方关闭连接。
socket.async_receive(boost::asio::buffer(buffer), handler);
socket.cancel();
在异步操作的启动函数中,将尝试进行非阻塞读取。 async_receive()
文档中记录了此行为的微妙之处:
Regardless of whether the asynchronous operation completes immediately or not, [...]
因此,如果操作立即完成并成功或出错,则完成处理程序将准备好调用并且不可取消。另一方面,如果操作会阻塞,那么它将被排入反应器进行监控,在那里它变得可取消。
通过在套接字上启用 non-blocking 模式,也可以获得与同步操作类似的行为。当套接字设置为非阻塞时,将阻塞的同步操作将失败并返回 boost::asio::error::would_block
.
socket.non_blocking(true);
auto bytes_transferred = socket.receive(
boost::asio::buffer(buffer), 0 /* flags */, error);
这是一个完整的例子demonstrating这些行为:
#include <array>
#include <iostream>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
// This example is not interested in the handlers, so provide a noop function
// that will be passed to bind to meet the handler concept requirements.
void noop() {}
void print_status(
const boost::system::error_code& error,
std::size_t bytes_transferred)
{
std::cout << "error = (" << error << ") " << error.message() << "; "
"bytes_transferred = " << bytes_transferred
<< std::endl;
}
int main()
{
using boost::asio::ip::tcp;
// Create all I/O objects.
boost::asio::io_service io_service;
tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), 0));
tcp::socket socket1(io_service);
tcp::socket socket2(io_service);
// Connect the sockets.
acceptor.async_accept(socket1, boost::bind(&noop));
socket2.async_connect(acceptor.local_endpoint(), boost::bind(&noop));
io_service.run();
io_service.reset();
std::array<char, 512> buffer;
// Scenario: async_receive when socket has no data.
// Within the intiating asynchronous read function, an attempt to read
// data will be made. If it fails, it will be added to the reactor,
// for monitoring where it can be cancelled.
{
std::cout << "Scenario: async_receive when socket has no data"
<< std::endl;
socket1.async_receive(boost::asio::buffer(buffer), &print_status);
socket1.cancel();
io_service.run();
io_service.reset();
}
// Scenario: async_receive when socket has data.
// The operation will complete within the initiating function, and is
// not available for cancellation.
{
std::cout << "Scenario: async_receive when socket has data" << std::endl;
boost::asio::write(socket2, boost::asio::buffer("hello"));
socket1.async_receive(boost::asio::buffer(buffer), &print_status);
socket1.cancel();
io_service.run();
}
// One can also get the same behavior with synchronous operations by
// enabling non_blocking mode.
boost::system::error_code error;
std::size_t bytes_transferred = 0;
socket1.non_blocking(true);
// Scenario: non-blocking synchronous read when socket has no data.
{
std::cout << "Scenario: non-blocking synchronous read when socket"
" has no data." << std::endl;
bytes_transferred = socket1.receive(
boost::asio::buffer(buffer), 0 /* flags */, error);
assert(error == boost::asio::error::would_block);
print_status(error, bytes_transferred);
}
// Scenario: non-blocking synchronous read when socket has data.
{
std::cout << "Scenario: non-blocking synchronous read when socket"
" has data." << std::endl;
boost::asio::write(socket2, boost::asio::buffer("hello"));
bytes_transferred = socket1.receive(
boost::asio::buffer(buffer), 0 /* flags */, error);
print_status(error, bytes_transferred);
}
}
输出:
Scenario: async_receive when socket has no data
error = (system:125) Operation canceled; bytes_transferred = 0
Scenario: async_receive when socket has data
error = (system:0) Success; bytes_transferred = 6
Scenario: non-blocking synchronous read when socket has no data.
error = (system:11) Resource temporarily unavailable; bytes_transferred = 0
Scenario: non-blocking synchronous read when socket has no data.
error = (system:0) Success; bytes_transferred = 6