Oops, this was meant for the list of course. --DD
---------- Forwarded message ---------
From: Dominique Devienne
Given the high connect time on Windows, I thought I'd try to keep the connection open on the client, and issue several send-request/read-response
On Wed, Nov 25, 2020 at 2:55 AM Dominique Devienne via Boost-users
wrote: pairs, using the Beast-based (sync) HTTP client, but only the first one works correctly, the 2nd errors out with: Error: An established connection was aborted by the software in your
host machine
This means that the server closed the connection. Are you setting HTTP/1.1 in the request? For HTTP/1.1 the default is to enable keep-alive. But for 1.0 the default is to close the connection.
Sorry for the delay. Just getting back to this. Yes, I'm in 1.1, and I verified that the request has Keep-Alive, and I'm (or the example, I don't recall) is setting the same value on the response.
it sounds like your connection is being closed after one request. Beast definitely supports keep-alive, so this is certainly user error. Please inspect the request/response messages taking place and post them on the list unmodified (use a wire sniffer for this if necessary) if you are still having problems.
Debugging this, I can see that the close arg to on_write is true, despite
the Keep-Alive on the response.
That response has an empty_body BTW, in case it matters. This route just
replies 200 OK or 403 Forbidden,
there's no body to return, only the headers matter to the client.
The reason why the connection is closed after the 1st request seems to be
because of need_eof().
The async server example has something like this in `send()`:
template <typename RES>
void send(RES&& msg) {
// The lifetime of the message has to extend
// for the duration of the async operation so
// we use a shared_ptr to manage it.
auto sp = std::make_shared<RES>(std::move(msg));
// Store a type-erased version of the shared
// pointer in the class to keep it alive.
res_ = sp;
bool need_eof = sp->need_eof();
ctx_.out() << "send: sp->need_eof() = " << need_eof << std::endl;
// Write the response
http::async_write(
stream_, *sp,
beast::bind_front_handler(
&session::on_write,
shared_from_this(),
sp->need_eof()
)
);
}
And `need_eof()` is true indeed. Which thus calls `on_write()` with `bool
close = true`,
resulting in a `do_close()` instead of waiting for the next request:
void on_write(
bool close,
beast::error_code ec,
std::size_t bytes_transferred
) {
boost::ignore_unused(bytes_transferred);
if (ec) {
return; // fail(ec, "write");
}
if (close) {
// This means we should close the connection, usually because
// the response indicated the "Connection: close" semantic.
ctx_.out() << "on_write: close()" << std::endl;
return do_close();
}
// We're done with the response so delete it
res_.reset();
// Read another request
do_read();
}
I stepped into `need_eof()`, and all conditions of the `if` are false,
resulting in the `return true` at the end.
template