读取:ASIO 中的文件结尾。为什么套接字会关闭?

v01*_*dya 5 c++ boost-asio

我有这样的示例(*)代码:

std::string protocol = "http";
std::string server = "www.example.com";
std::string path = "/";

asio::io_service service;

asio::ip::tcp::resolver resolver(service);
asio::ip::tcp::resolver::query query(server, protocol);

asio::ip::tcp::socket socket(service);

asio::ip::tcp::resolver::iterator end;
auto it = resolver.resolve(query);
asio::error_code error;
socket.connect(*it, error);
while(error && ++it!=end)
{
    socket.close();
    socket.connect(*it, error);
}

asio::streambuf request;
std::ostream request_stream(&request);

request_stream << "GET " << path << " HTTP/1.0\r\n";
request_stream << "Host: " << server << "\r\n";
request_stream << "Accept: */*\r\n";
request_stream << "Connection: close\r\n\r\n";

asio::streambuf response;
size_t s = asio::read(socket, response);
Run Code Online (Sandbox Code Playgroud)

什么时候asio::read被调用我得到:

terminate called after throwing an instance of 'boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<std::system_error> >'
  what():  read: End of file
Run Code Online (Sandbox Code Playgroud)

据我了解,发生此错误是因为尝试读取时套接字已关闭。但我不明白为什么它会关闭。

我原来在read_until那里,它有同样的错误。

我是否在启动连接时做错了什么,还是因为其他原因被终止了?

(*) 示例意味着,它是一个示例,而不是一个完整的工作程序。如果示例可以缩短或更好,请随时编辑问题。


根据 sehe 的回答,我尝试了以下操作:

size_t s = asio::read(socket, response, error);

if(!error || error==asio::error::eof)
{
    if(s==0)
    {
        std::cerr << "Same problem" << std::endl;
    }
}
Run Code Online (Sandbox Code Playgroud)

结果是在运行程序时显示“Same problem”,这意味着它在读取任何数据之前都获得了EOF。


根据 YSC 的回答,我尝试了以下方法:

for (;;)
{
    char buf[255];

    size_t len = socket.read_some(asio::buffer(buf, 255), error);

    if (error == asio::error::eof)
    {
        std::cout << std::endl << "Connection closed" << std::endl;
        break; // Connection closed cleanly by peer.
    }
    else if (error)
    {
        std::cerr << "Error" << std::endl;
        return 1;
    }

    std::cout.write(buf, len);
}
Run Code Online (Sandbox Code Playgroud)

没有数据出现,并在稍有延迟后显示“连接已关闭”。这意味着我也使用这种方法获得了没有任何数据的 EOF。

seh*_*ehe 8

只需处理错误情况:http://www.boost.org/doc/libs/1_59_0/doc/html/boost_asio/reference/read/overload2.html

asio::streambuf response;
boost::system::error_code ec;
size_t s = asio::read(socket, response, ec); // no condition, so read till EOF

if (!ec || ec == boost::asio::error::eof) {
    // woot, no problem
}
Run Code Online (Sandbox Code Playgroud)

  • 是的。完全一样的事情。我得到 EOF 但没有数据。 (4认同)
  • 你好。谢谢,但是,正如我之前所说,我的实际代码实际上是不同的。问题不是“我如何处理 EOF”,而是“为什么我得到 EOF,而不是数据”。我会尝试你的方法(还没有),但我怀疑我只会在`s`中写入0,并且我最终会在`if`中没有数据和`// woot,同样的问题`。 (3认同)

YSC*_*YSC 0

您的socket方法read_some()在关闭时不会抛出,而是返回boost::asio::error::eof

您可能会发现这个增强教程很有用。

  • 抱歉,这个问题怎么回答?就像医生说“你病了”。 (2认同)