我目前在使用 boost::asio 时遇到问题,我想像下面的代码一样编写和读取。写入工作正常,但读取总是返回零。其实我也发现每个网站都指的是
read_some
函数而不是
readsome
函数库中我的系统...
有人可以给我一些提示吗?
boost::asio::ip::tcp::iostream tcp_stream;
tcp_stream.connect("localhost", "12345");
while(1)
{
char inp[6]={0,0,0,0,0,0};
tcp_stream<<"Test"<<std::endl;//Works fine get it with netcat (nc -l 12345)
size_t r = tcp_stream.readsome(inp,5);//Always 0
//std::string a;
//tcp_stream>>a; //Works but blocks and gives me all bytes it has.
//std::cout<<a<<std::endl;
//std::cout<<"RDBUF: "<<tcp_stream.rdbuf();
//rdbuf blocks here, never resuming and outputting
//everything I write with netcat to command line...
if(r>0)
{
std::cout<<inp<<std::endl;
}
else //<<< always goes here
{
std::cout<<"received nothing!"<<std::endl;
}
sleep(1);
}
我想要的是我从当前界面读取0-5个字节。 (非阻塞)
最佳答案
问题是 std::basic_istream<>::read_some()
将从关联的 streambuf
读取的输入序列,以及 asio::basic_socket_streambuf
的输入序列包括已从套接字读取但尚未从流缓冲中使用的数据。它不包括无需阻塞即可从套接字读取的数据。[1]
要变通解决此行为,可以确定可读取的数据量而不阻塞 streambuf 及其底层套接字,然后发出 std::basic_istream<>read()
。操作:
/// @brief Read up to `n` characters from `stream` and store them
/// into `buffer` without blocking. This may not read all
/// of the requested amount of bytes.
template <typename... Args>
std::streamsize readsome(
boost::asio::basic_socket_iostream<Args...>& stream,
char* buffer,
std::streamsize n)
{
std::streamsize available =
stream.rdbuf()->in_avail() // available on input sequence
+ stream.rdbuf()->available(); // available on socket
n = std::min(n, available);
if (n == 0) return 0;
stream.read(buffer, n);
return n;
}
这是一个完整的例子demonstrating此功能:
#include <chrono> // std::chrono::seconds
#include <iostream> // std::cout, std::endl
#include <string> // std::to_string
#include <thread> // std::thread
#include <boost/asio.hpp>
/// @brief Read up to `n` characters from `stream` and store them
/// into `buffer` without blocking. This may not read all
/// of the requested amount of bytes.
template <typename... Args>
std::streamsize readsome(
boost::asio::basic_socket_iostream<Args...>& stream,
char* buffer,
std::streamsize n)
{
std::streamsize available =
stream.rdbuf()->in_avail() // available on input sequence
+ stream.rdbuf()->available(); // available on socket
n = std::min(n, available);
if (n == 0) return 0;
stream.read(buffer, n);
return n;
}
int main()
{
using boost::asio::ip::tcp;
const std::array<char, 6> expected_data = {100, 101, 102, 103, 104, 105};
// Create all I/O objects.
boost::asio::io_service io_service;
tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), 0));
tcp::socket socket(io_service);
// Run stream in its own thread.
std::thread client_thread(
[&]
{
// Connect the stream to the acceptor.
auto endpoint = acceptor.local_endpoint();
tcp::iostream stream(endpoint.address().to_string(),
std::to_string(endpoint.port()));
// Block until 6 bytes are available.
while (stream.rdbuf()->available() < 6)
{
std::this_thread::sleep_for(std::chrono::seconds(1));
}
// Read 1 byte out of the 6 avaialble.
std::array<char, 6> actual_data{};
auto bytes_transferred = readsome(stream, begin(actual_data), 1);
assert(bytes_transferred == 1);
assert(std::equal(
begin(actual_data),
begin(actual_data) + bytes_transferred,
begin(expected_data)));
// Attempt to read 6 bytes, although only 5 are available.
bytes_transferred = readsome(stream, begin(actual_data),
sizeof actual_data);
assert(bytes_transferred == 5);
assert(std::equal(
begin(actual_data),
begin(actual_data) + bytes_transferred,
begin(expected_data) + 1));
// Attempt to read 6 more bytes, even though 0 bytes are available.
bytes_transferred = readsome(stream, begin(actual_data),
sizeof actual_data);
assert(bytes_transferred == 0);
});
// Connect the sockets then write to the stream.
acceptor.accept(socket);
boost::asio::write(socket, boost::asio::buffer(expected_data));
// Wait for the stream to complete.
client_thread.join();
}
<子>1。 tcp::stream
文档及其相关类没有很好的记录。我不够精通,不知道这种行为是故意的、错误的,还是只是被忽视了。当前 networking-ts draft 中的文档仍然相当简洁.
关于c++ - boost::asio readsome 函数似乎不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38037991/