[英]boost::asio readsome function does not seem to work
I am currently experiencing troubles using boost::asio, I want to write and read like in the following piece of code. 我目前在使用boost :: asio遇到麻烦,我想像下面的代码那样进行读写。 Write works fine, but reading always returns zero.
写入工作正常,但读取始终返回零。 Actually I also found out that every site refers to the
实际上,我还发现每个站点都引用了
read_some
read_some
function instead of the 功能而不是
readsome
好看的
function I have on my system in the library ... 我的系统在图书馆的功能...
Anybody who can give me a hint on this? 有人可以给我提示吗?
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);
}
What I would like to have is that I read 0-5 bytes from the current interface. 我想从当前接口读取0-5个字节。 (non-blocking)
(非阻塞)
The issue is that std::basic_istream<>::read_some()
will read from the associated streambuf
's input sequence, and the asio::basic_socket_streambuf
's input sequence includes data that has been read from the socket, but not yet consumed from the streambuf. 问题是
std::basic_istream<>::read_some()
将从关联的streambuf
的输入序列中读取,而asio::basic_socket_streambuf
的输入序列包含已从套接字读取但尚未使用的数据从streambuf。 It does not include data that is available to be read from the socket without blocking. 它不包括可无阻塞地从套接字读取的数据。 [1]
[1]
To work around this behavior, one could determine the amount of data available to be read without blocking from both the streambuf and its underlying socket, then issue a std::basic_istream<>read()
operation: 要解决此问题,可以确定可读取的数据量,而不会阻塞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;
}
Here is a complete example demonstrating this functionality: 这是演示此功能的完整示例:
#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. The tcp::stream
documentation and its related classes are not well documented. 1.
tcp::stream
文档及其相关类的文档不完整。 I am not versed enough to know if this behavior is intentional, a bug, or has merely been overlooked. 我不了解这种行为是故意的,错误的,还是只是被忽略了。 The documentation still remains fairly terse in the current networking-ts draft .
在当前的网络-ts草案中 ,文档仍然很简洁。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.