Persistent Connections and Pipelined Requests
The HTTP package classes are implemented with support for both persistent connections and pipelined requests, as described in RFC 2616. Persistent connections allow for multiple request-response pairs to be executed over a single connection. This behavior reduces the cost of latency that occurs during connection.
NOTE: The HTTP package classes support persistent connections under HTTP/1.1 whenever possible.
Pipelined requests occur when multiple requests are issued over a persistent connection without waiting for a reply from the previous requests. By issuing a series of requests, the time available between sending a request and receiving the reply can be used to issue more requests. If a series of requests is issued in this way, time is saved.
Pipelining includes risk. If a request has a side effect on the server, a pipelined request might generate and prepare a response before a prior requests’ side effect is completed. If the side effect has an impact on what would have been returned if it had completed, the pipelined response to the second request may not be accurate. The following table gives an example of this situation.
Without Pipelining | With Pipelining |
---|
Client Request 1: Remove Document A | Client Request 1: Remove Document A |
Server Action: Send “Document A Removed Message” | Client Request 2: Get Document A |
Server Action: Remove Document A | Server Action: Send “Document A Removed Message” |
Client Received: Document A Removed | Server Action: Send Document A |
Client Request 2: Get Document A | Server Action: Remove Document A |
Server Action: Send “Document A does not exist Message” | Client Received: Document A Removed |
Client Received: Document A does not exist | Client Received: Document A |
If you determine that a series of actions can be performed safely in a pipeline, you can issue a series of pipelined requests using the
RWHttpClient class and pass an additional parameter to the submit request.
Example 20 issues two requests to the same server without waiting for a reply.
NOTE: Servers and files shown in the code might not exist and are included as examples only.
Example 20 – Using pipelined requests
RWHttpClient client = RWHttpSocketClient::make();
client.connect("www.perforce.com");
RWHttpRequest root(RWHttpRequest::Get, "/");
RWHttpRequest products(RWHttpRequest::Get, "/products/");
client.submit(root, RW_HTTP_ALLOW_PIPELINING);
client.submit(products, RW_HTTP_ALLOW_PIPELINING);
RWHttpReply rootReply = client.getReply();
RWHttpReply productsReply = client.getReply();
For more information about the dangers of pipelining, see section 8.1.2.2 and section 9.1.2 of RFC 2616.
NOTE: RWHttpAgent does not include a mechanism for specifying pipelined requests, but it does use persistent connections internally to reduce latency due to handshaking during connections.