提供MCVE会很困难,方案如下:
有自定义标题,大多数通信都是使用multipart / form完成的。 但是,在服务器返回401以进行未授权访问的情况下, 客户端收到损坏的管道(系统错误32)。
AFAIK当服务器连接过早关闭时会发生这种情况。 因此,运行到gdb,我可以看到问题确实是从发送请求的async_write到读取HTTP头的第一行的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
回调,检查请求是否已发送正常,然后读取第一行(直到第一个换行符):
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
和适当的请求,我们确实在服务器关闭连接之前得到了实际的消息/错误我真的很感激任何提示或提示。我知道如果没有代码很难提供帮助,那么我可以随时添加更多源代码。
如果我不检查写入请求和阅读服务器回复之间的错误,那么我确实得到了实际的HTTP 401错误。然而,这似乎是违反直觉的,我不确定为什么会发生这种情况或是否应该发生。
答案 0 :(得分:3)
根据HTTP规范允许观察到的行为。
客户端或服务器可以随时关闭套接字。在客户端完成传输请求之前,服务器可以提供响应并关闭连接。在编写正文时,建议客户端监视套接字是否有错误或关闭通知。来自RFC 7230, HTTP/1.1: Message Syntax and Routing Section 6.5. Failures and Timeouts:
<强> 6.5。失败和超时
客户端,服务器或代理可以随时关闭传输连接。 [...]
发送邮件正文的客户端应该在传输请求时监视网络连接以获取错误响应。如果客户端看到一个响应,指示服务器不希望接收消息正文并且正在关闭连接,则客户端应该立即停止传输正文并关闭其连接端。
在正常连接关闭时,服务器将在关闭底层套接字之前向客户端发送响应:
<强> 6.6。拆除强>
发送&#34;关闭&#34;的服务器连接选项必须在发送包含&#34;关闭&#34;的响应后启动连接关闭[...]。 [...]
鉴于上述行为,有三种可能的情况。 async_write()
操作以:
考虑:
如果async_read()
成功或有可供阅读的数据,则启动async_write()
操作
void write_request(
const boost::system::error_code & error,
const std::size_t bytes_transferred)
{
// The server may close the connection before the HTTP Request finished
// writing. In that case, the HTTP Response will be available on the
// socket. Only stop the call chain if an error occurred and no data is
// available.
if (error && !socket_->available())
{
return;
}
boost::asio::async_read_until(*socket_, buffer_, "\r\n", ...);
}
根据RFC 建议,在async_read()
的同时启动async_write()
操作。如果服务器指示HTTP连接正在关闭,则客户端将关闭其套接字的发送端。额外的状态处理可能无法保证额外的复杂性