I'm having troubles with understanding how SPDY can solve HOL blocking.
Quote from: http://chimera.labs.oreilly.com/books/1230000000545/ch02.html#TCP_HOL
To understand why that is the case, recall that every TCP packet carries a unique sequence number when put on the wire, and the data must be passed to the receiver in-order (Figure 2-8). If one of the packets is lost en route to the receiver, then all subsequent packets must be held in the receiver’s TCP buffer until the lost packet is retransmitted and arrives at the receiver. Because this work is done within the TCP layer, our application has no visibility into the TCP retransmissions or the queued packet buffers, and must wait for the full sequence before it is able to access the data. Instead, it simply sees a delivery delay when it tries to read the data from the socket. This effect is known as TCP head-of-line (HOL) blocking.
So HOL blocking exists because TCP guarantees in-order delivery. But here the user igrigorik says that SPDY allows for the packet to come in different order. But isn't SPDY just a HTTP replacement? Meaning it still runs over TCP (from here).
HOLB has several causes, of which packet retransmission is one, but it's not the one relevant to HTTP and SPDY.
The one relevant to HTTP and SPDY is the fact that in HTTP 1.x multiple requests must be responded in order.
Imagine a HTTP client that sends to a server 2 requests over the same TCP connection, and that the first response is "large" in content length while the second response is "small" in content length.
Due to the nature of the HTTP 1.x protocol, the second response must wait for the first response to complete. The second response is head-of-line blocked by the first response.
With multiplexed protocols like SPDY and HTTP 2, instead, this type of HOLB does not exist, because the second "small" response can arrive to the client well before the first "large" response (they can even be interleaved).
The diagram of the question you referenced above explains it graphically.
Ilya, in his response, was not referring to TCP packets, but to HTTP "packets" when he was saying that they can be out of order. Imagine a "packet" made of the HTTP headers, and a "packet" made of POST data to be uploaded to the server (or, in a response, "packets" made of the data to be downloaded to the client).
In HTTP 1.x, these HTTP "packets" must be in order (first all the HTTP "packets" of request 1, then all the HTTP "packets" of request 2; or first all the HTTP "packets" of response 1 and then all the HTTP "packets" of response2), while in SPDY and HTTP 2 they may be out of order or even interleaved.
The lack of this kind of HOLB in SPDY and HTTP 2 makes these protocols more efficient than HTTP 1.x.
The HOLB caused by TCP retransmissions affects any TCP based protocol, included multiplexed protocols like SPDY and HTTP 2, and duplex protocols like HTTP 1.x.
Related
I'm an application developer, looking into trying to understand how HTTP request/responses are passed at the transport layer, and found some good resources that have been helping me, but there are still some questions I can't track down
How is HTTP converted to TCP?
This thread helped me understand that as a request is passed down each layer, the layer is "encapsulating" the payload with headers until it's sent over the wire
So my current understanding is that the HTTP Request is really a payload, which then the TCP layer will throw some headers on. These headers seem to mostly be used to track the order of the packets of the messages that will be going back-and-forth
TCP Headers:
And then IP headers are slapped on (https://www.thegeekstuff.com/2012/03/ip-protocol-header/)
Which just track the source/destination and size of the packet
It's clear that a every HTTP request does not map 1:1 to a packet, based on what I have found it looks like the requests can be broken up into pieces to be streamed over TCP
If the request needs to be broken up, where is the code that does that?
Client Send SYN with client isn.
Server reply SYN ACK with server's isn.
Client resend SYN if timeout?
When client send data, it can accumulated confirm the server's isn.
I try to search, but can't find the answer.
I know how the tcp is designed now, I just don't know why it's designed like this. Why can't use a two way handshake.
It cannot use a two way handshake by definition. TCP/IP is formalized as a standard for communication across networks (Internetworking). Specifically, RFC 793 requires that:
The "three-way handshake" is the procedure used to establish a
connection. This procedure normally is initiated by one TCP and
responded to by another TCP. The procedure also works if two TCP
simultaneously initiate the procedure. When simultaneous attempt
occurs, each TCP receives a "SYN" segment which carries no
acknowledgment after it has sent a "SYN". Of course, the arrival of
an old duplicate "SYN" segment can potentially make it appear, to the
recipient, that a simultaneous connection initiation is in progress.
Proper use of "reset" segments can disambiguate these cases.
If you think about how the protocol works, you do not actually have a single full duplex connection. Instead, you have two simplex connections, each going in one direction. This is why the proper response to a SYN is a SYN-ACK. The server is acknowledging the synchronization request by sending the originators sequence number as the acknowledgement number plus one; it is simultaneously attempting to open its own connection to the client by sending a SYN request to synchronize.
The proper answer to a SYN will always be an ACK, even if the connection fails.
Regarding your question about sending a retry, yes; the client will send a retry (typically up to three, but it could be as many as eight in practice... There's no limit defined) attempting to elicit a response of some kind (preferably a SYN-ACK, but possibly a RST-ACK).
wondering whether any one can provide a convincing explanation about the whether HTTP 1.1 is half duplex or full duplex in the context of pipelining? As far as I understand,multiple requests can be send over the same persistent connection before the client gets the response. So does that mean that server can respond for the previous request while client sends a new request?
HTTP is request-response protocol. The client sends request. The server waits till the complete request is received. Then sends a response. The client and server cannot send simultaneously.
Full Duplex channel implies that client and server can send data simultaneously. Phone lines are example of Full Duplex. To achieve full duplex in Web, Web sockets is the recommended standard. Once a Web socket connection is established, both parties can exchange messages simultaneously. Web sockets work on top of TCP and does not use the HTTP protocol.
Let's have a look at the standard, in this case RFC-2616. There we find in paragraph 8.1.1, Persistent connections:
- HTTP requests and responses can be pipelined on a connection.
Pipelining allows a client to make multiple requests without
waiting for each response, allowing a single TCP connection to
be used much more efficiently, with much lower elapsed time.
and a bit later in the document:
8.1.2.2 Pipelining
A client that supports persistent connections MAY "pipeline" its
requests (i.e., send multiple requests without waiting for each
response). A server MUST send its responses to those requests in the
same order that the requests were received.
As in both cases it's clearly stated that the client can send requests without waiting for a response, I think it's safe to state that HTTP 1.1 supports full-duplex.
EDIT: in RFC-7230, part of the RFC set that replaces RFC-2616, this statement becomes:
A client that supports persistent connections MAY "pipeline" its
requests (i.e., send multiple requests without waiting for each
response). A server MAY process a sequence of pipelined requests in
parallel if they all have safe methods (Section 4.2.1 of [RFC7231]),
but it MUST send the corresponding responses in the same order that
the requests were received.
Most implementations do allow full-duplex HTTP (for 2xx responses).
A formal discussion can be found at
https://datatracker.ietf.org/doc/html/draft-zhu-http-fullduplex
As it is using tcp, that doesn't mean every application protocol on tcp is a full duplex.
HTTP uses a request-response paradigm, not a full-duplex streaming paradigm. Let me repeat it: HTTP is a request-response protocol! This means that the client sends a request, and when the complete request has been sent then the server sends the response. This is the case even if so-called keep-alive is used, i.e. multiple requests are sent over the same TCP connection. Because this behaviour is fundamental to the protocol most implementations make certain (valid) assumptions which make it difficult to create a full-duplex connection.
If you want a full duplex go for websockets, which are designed for an entirely different purpose.
We are trying to implement a proxy proof of concept but have encountered an interesting question: Since a single HTTP connection can, and indeed should, make multiple requests, and the HTTP transactions are sent via multiple packets due to TCP's magic, is it possible for a HTTP request to begin in the middle of a packet?
Bear in mind that this is not a theoretical question regarding possible optimization of the browser, but whether it actually happens in real life. It would be even better if someone could point me to a written reference on whether or not this is possible and if so how often it can occur.
Clarification update: We know that if we work in the HTTP layer alone we would not need to bother with this question, however we're trying to figure out if some advanced technique could be applied by working on the TCP layer first.
Assuming that you are talking about IP packets: Yes, it is possible that HTTP request starts middle of IP packet.
When you are using persistent HTTP connections, that is, using same TCP connection for several HTTP requests, it is fully possible that request boundary is middle of IP packet.
Also there is a TCP protocol between IP and HTTP. TCP contains also some headers so a IP packet may start with some TCP headers and rest of the packet consists of HTTP request.
HTTP request may also consist of several IP packets (in case of file uploads, transmission errors and following retransmissions etc).
However, I wonder why you are interested in packets if you are working at HTTP level. TCP should hide the IP packet details.
First of all, TCP is a stream based protocol and has no concept of packets. HTTP itself might have some kind of message or record delimiter, but TCP doesn't.
This page might be helpful: Structure of HTTP Transactions
From your question it sounds like you think that each read from a TCP socket is a "packet" of data. In reality, each read simply reads as many bytes as are in the buffer up to the maximum that you requested, without any concept of records or packets.
So for instance, lets say you read 2048 bytes from the socket, you could have the tail end of one transaction, followed by the beginning of a second response half way through the data you read, and only get the remainder of your second response on your next read from the socket.
If you're here in Jerusalem or near by maybe I could help you out.
Unless you are implementing your own TCP stack, you should not need to worry about the packets, but rather about the API that the TCP provides, in case of POSIX interfaces it would be the recv() or read(). So I treat the question then as "Can more than one HTTP requests come into a single read(), and can the HTTP request be split between multiple read() requests?" -- The answer to both would be "yes, it is possible".
An example of where this can happen is HTTP pipelining. This not frequent in real life (ironically, at least some of the browsers disable it by default because of "buggy proxies" :-) - but when it happens, can be a bit of a problem for the users to diagnose - especially if they have no access to the proxy.
One very notable place where it does happen by default apt-get in Debian-derived linux systems. Just install a Debian or Ubuntu server and try to use it through your proxy. You can do that by editing the /etc/apt/apt.conf.d/proxy file and placing the following there:
Acquire::http::Proxy "http://your.proxy.address:8080";
Depends of which abstraction layer of a packet you are talking about: there are many layers underneath HTTP.
HTTP --> TCP (byte stream) --> IP (packet) --> (possibly something else) Ethernet (frame) --> (possibly) some other transport
If you are talking about the IP layer, then yes the HTTP layer would start later on... Note that TCP presents a "byte stream interface" to its Client layer hence, no concept of packet here.
I think I understand where you are trying to go with this question.
If you don't use persistent HTTP connections, the HTTP GET request header is always the very first thing which is sent over the TCP connection, so we can be sure that the start of the HTTP GET request header does "not start in the middle of some TCP packet". But keep in mind that there may be one or more TCP packets without any user data, e.g. only a SYN, which may preceed the TCP packet with the start of the HTTP GET request header. And also keep in mind that the HTTP GET request header may not be contained in a single TCP packet.
If you do use persistent HTTP connections, the start of the HTTP GET request header for request number N+1 can start in the middle of a TCP packet, namely after the end of HTTP GET request body of request number N.
If you are asking these questions you are possibly "doing it wrong". As several other responders have already pointed out, in the vast majority of cases you should probably just be a TCP client and deal with a TCP stream of data and let the TCP code worry about the TCP packets. (Unless, of course, you are working on some special hardware which is looking at individual IP packets as they fly by and try to do some processing at the HTTP layer.)
If I make multiple HTTP Get Requests to the same server and get HTTP 200 OK responses to each one how do I tell which request maps to which response using Wireshark?
Currently it looks like an http request is made, and the next HTTP 200 OK response is quickly received so everything is in a the proper sequence. I have seen things to the contrary however. For example using the Google Maps API v2 I've made several requests for location information and then the information is received in an arbitrary order (closely resembling the order in which I requested it, but not necessarily perfect.)
So my intuition is I cannot assume that my responses will be received in a specific order, even though they may be in order most of the time. So I'm wondering how I can determine this order from the response.
Update: Clarification as to what I need. I just need to know that the server has received the request. It seems like I need to do this by looking at sequence numbers and perhaps even ACKS. The reasoning behind this approach is I'm basically observing a web app and checking it is sending the information and the information is being received.
Update: This has nothing to do with wireshark specifically. I believe it is confusing people so I removing it from the title. It has to do with the HTTP protocol on top of the TCP/IP protocol and how we map responses to requests.
Thanks.
After you have stopped capturing packets follow this steps:
position the cursor on a GET request
Open the Analyze menu
click "Follow TCP Stream"
You get a new window with requests and responses in sequence.
While I was googling for a complete different question, I saw this one and I think I can provide a more complete answer :
HTTP dictates that responses must arrive in the order they were requested, Therefore, if you are looking at a single TCP connection at a given time you should be seeing :
Request ; Response ; Request ; Response ...
Also in HTTP/1.1, there is support for "Pipeline" where the client doesn't have to wait for responses to arrive in order to issue the next request. What could be observed in such cases is :
Request ; Response ; Request ; Request ; Response ; Response ; Request ; Response
In the HTTP response itself, there is no reference to the specific request that triggered it.
Filipo's suggestion is classic when debugging / observing a single TCP connection, but, when observing multiple TCP connections, you can't click the follow TCP Stream because you'd have to do it for each connection.
If you have many TCP connections, and many requests/responses you will have to look at TCP Source port in the request packet, and the TCP dest port in the response packet to know which response is related to each tcp connection, and then apply the HTTP request/response order rules.
Also, Wireshark CAN decompress the response body, and it will do it automatically if all the response body has arrived, but it will do so NOT in the Follow TCP Stream.
I always use Wireshark to debug HTTP.
Seems like this ability is not provided by the HTTP protocol at the application layer so I must go down to the transportation layer to determine this. In my case the TCP/IP layer using sequence numbers.
HTTP only presumes a reliable
transport; any protocol that provides
such guarantees can be used; the
mapping of the HTTP/1.1 request and
response structures onto the
transport data units of the protocol
in question is outside the scope of
this specification.
Read more:
http://www.faqs.org/rfcs/rfc2616.html#ixzz0e20kxKcz
Don't use Wireshark to debug HTTP, use an HTTP debugger such as Fiddler2