我目前遇到使用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个字节。 (非阻塞)
答案 0 :(得分:1)
问题在于std::basic_istream<>::read_some()
会从关联的streambuf
输入序列中读取,而asio::basic_socket_streambuf
的输入序列包含已读取的数据从套接字,但尚未从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。