【发布时间】:2016-12-15 13:23:10
【问题描述】:
提供MCVE 会很困难,场景如下:
- 用 c++ 编写的带有 boost asio 的服务器提供了一些服务
- 用 c++ 编写的带有 boost asio 请求服务的客户端
有自定义标题,并且大多数通信都是使用 multipart/form 完成的。 但是,在服务器返回 401 表示未授权访问的情况下, 客户端收到损坏的管道(系统错误 32)。
当服务器连接过早关闭时会发生这种情况。 因此,运行到 gdb,我可以看到问题确实是从发送请求的 async_write 到读取 HTTP Header 第一行的 async_read_until 的转换:
connect 例程将请求从客户端发送到服务器:
boost::asio::async_write(*socket_.get(),
request_,
boost::bind(&asio_handler<http_socket>::write_request,
this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
还有write_request回调,检查请求是否发送OK,然后读取第一行(直到第一个换行):
template <class T>
void asio_handler<T>::write_request(const boost::system::error_code & err,
const std::size_t bytes)
{
if (!err) {
// read until first newline
boost::asio::async_read_until(*socket_,
buffer_,
"\r\n",
boost::bind(&asio_handler::read_status_line,
this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
else {
end(err);
}
}
问题是end(err) 总是被一个损坏的管道调用(错误代码32)。据我了解,这意味着服务器关闭了连接。服务器确实关闭了连接,但只有在它发送了一条消息HTTP/1.1 401 Unauthorized。
- 将
curl与适当的请求一起使用,我们确实会在服务器关闭连接之前收到实际的消息/错误 - 使用我们用 C++/boost asio 编写的客户端,我们只能得到损坏的管道,没有数据
- 只有当服务器保持连接打开时,我们才会读取错误 (401) 但这违背了目的,因为现在连接保持打开状态。
我非常感谢任何提示或提示。我知道没有代码很难提供帮助,因此我可以随时添加更多源代码。
编辑:
如果我不检查写入请求和读取服务器回复之间的错误,那么我确实会收到实际的 HTTP 401 错误。然而,这似乎违反直觉,我不确定为什么会发生这种情况或是否应该发生这种情况。
【问题讨论】:
-
服务器是否需要读取整个HTTP请求来判断和响应未经授权的?例如,也许授权可以仅从标头字段确定,从而无需读取任何多部分/表单主体。在这种情况下,服务器可以在客户端完成写入请求之前发送响应并关闭连接。
-
@TannerSansbury 不,它只需要标题值来回复。是的,这就是正在发生的事情,服务器在收到整个请求之前正在回复。我假设(是的,我知道......)在服务器完成接收请求之后会出现回复,显然情况并非如此。非常感谢您的帮助!
标签: c++ boost boost-asio