What is the WebSockets alternative in the HTTP/2 world? - websocket

The new HTTP/2 protocol comes with some promising features. Some of them:
Multiplexing - a single TCP connection can be used to make multiple HTTP/2 requests and receive multiple responses (to a single origin)
HTTP/2 Server Push - sending server responses to the client without receiving requests, i.e. initiated by the server
Bidirectional connection - HTTP/2 spec - Streams and Multiplexing:
A "stream" is an independent, bidirectional sequence of frames
exchanged between the client and server within an HTTP/2 connection.
The motivation behind HTTP/2 is explained here HTTP/2 FAQ:
HTTP/1.1 has served the Web well for more than fifteen years, but its
age is starting to show.
and
The goal of the Working Group is that typical uses of HTTP/1.x can use HTTP/2 and see some benefit.
So HTTP/2 is nice and comes to replace HTTP/1.x. Unfortunately, HTTP/2 does not support WebSockets. In this question Does HTTP/2 make websockets obsolete? it is made clear that the HTTP/2 Server Push is not an alternative, neither are Server-Sent Events.
Now to the question: What do we use if we want WebSockts functionality over HTTP/2?

Current forms of HTTP/2 Protocol Negotiation:
HTTP/2 connections start in one of three ways:
In an encrypted connection (TLS/SSL) using ALPN (Application Layer Protocol Negotiation). Most browsers require TLS/SSL for HTTP/2 and use this method for HTTP/2 connection establishment.
In clear text, using the HTTP/1.1 Upgrade header (same as Websockets). Most browsers require TLS/SSL for HTTP/2, so this is limited in it's support.
In clear text, using a special string at the beginning of an HTTP/1.1 connection (which could allow HTTP/2 servers in clear text to disable HTTP/1.1 support). Limited client support.
Negotiating the Websocket Protocol, present tense:
Negotiating Websocket connections, at the moment, requires HTTP/1.1 support and makes use of the HTTP/1.1 Upgrade header.
This is often performed by the same application server that listens to the HTTP/1.1 and HTTP/2 connections. Web applications that support concurrency (whether evented or thread based) are usually protocol agnostic (as long as HTTP semantics are preserved) and work well enough on both protocols.
This allows HTTP data to be used during connection establishment (and perhaps effect the Websocket connection state/authentication procedure).
Once the Websocket connection is established, it's totally independent from the HTTP semantics / layer.
Negotiating the Websocket Protocol in an HTTP/2 world:
In an HTTP/2 (only) world, which might be a while into the future, there could be a number of possible approaches to Websocket protocol negotiation: an ALPN based approach and an HTTP/2 "tunnel" (or "stream") approach.
The ALPN approach preserves protocol independence at the expense of the pre-upgrade (HTTP) stage, while the "stream" approach provides the HTTP pre-"upgrade" (or Connect) stage at the expense of high coupling and complexity.
The ALPN Approach:
One possible future approach will simply add the Websocket protocol to the ALPN negotiation table.
At the moment, ALPN is used to select (or default to) the "http/1.1" protocol and the Upgrade request is handled by the HTTP/1.1 server. Which means that Websocket still provides us with the HTTP header data during protocol negotiation (while using it's own TCP/IP connection)
In the future, ALPN might simply add "wss" as an available choice.
Using this approach, the Websocket (which is currently established using the HTTP/1.1 Upgrade header, both in encrypted and clear text forms) could easily be negotiated using the ALPN extension to the TLS/SSL layer.
This will keep the Websocket protocol independent from the HTTP/2 protocol and allow it's use even when HTTP isn't supported.
However, this will come with the downside that cookies and other HTTP headers might be no longer available as part of the protocol negotiation. Another difference (both good and bad) is that this approach will require a separate TCP/IP connection.
The HTTP/2 "tunnel" / "stream" approach
Another possible future approach, which is reflected in this proposed draft, will dispose of the HTTP/1.1 variation of the Websocket protocol in favor of an HTTP/2 "stream" approach.
HTTP/2 "streams" are the way HTTP/2 implements multiplexing and allows multiple requests to be handled concurrently. Each request receives a stream number ID and any data pertaining to this request (headers, responses etc') is identified using the same numerical stream ID.
Under this approach, "Websocket" data will be contain within the HTTP/2 wrapper and the stream ID will be used to identify the "Websocket" stream.
Although this might provide some benefits (HTTP headers and cookies could be provided as part of the Websocket negotiation), it's not without its downfalls.
Higher complexity and tighter protocol coupling are just two examples, both of which are very serious downfalls.
Conclusion:
At the time of this writing, HTTP/1.1 Upgrade semantics are required for Websocket connections, both when using clear text (ws) and encrypted (wss) connections.
The future is, as of yet, undecided and it will probably take a long time before the current Upgrade process (using HTTP/1.1) is phased out

Well your timing is rather apt!
A new version of the internet standards draft was literally just published:
Bootstrapping WebSockets with HTTP/2
Additional information here:
https://github.com/mcmanus/draft-h2ws/blob/master/README.md
And you can follow the discussion in it here:
https://lists.w3.org/Archives/Public/ietf-http-wg/2017OctDec/0032.html
Until this is approved, and then implemented by browsers and servers, I would say that Daniel Haxx’s post that you included in your question represents a very good summary of the current status.

One of your links actually has one answer: you can just use SSE.
Semantically, you can achieve the same things with either websockets or (SSE + POST ). The view that the two technologies address different use cases is, roughly speaking, bikeshedding around "this syntax works better for this".
There are ongoing efforts to port something similar to websockets to HTTP/2, but unless those technologies make possible new uses cases or efficiencies, I see no point.

Related

Is there a reason why HTTP2 is required when websocket is already available?

Is there a reason why HTTP2 is required when websocket is already available?
Nathan Aw (Singapore)
Why do we need HTTP/2 when we have WebSockets? Well why did we need WebSockets when we have TCP? Or even IP? Protocols are basically agreed standards that can be implemented by independent parties.
WebSockets are good for two way communication but are mostly unstructured on top of that and application specific. HTTP is (mostly) a series of one-way requests to the server (ask for a resource, receive an answer) — though HTTP/2 enhances that slightly with HTTP/2 push and the binary framing layer could in theory be used more for proper two way push. So the full two way nature of WebSockets — the very thing they are good at — is not really needed for most HTTP use cases.
Looking at HTTP, it has various extras that WebSockets does not have. Including defined methods, headers and compression. This allows a well-defined understanding between various HTTP implementations to facilitate communications for its use case including features like multiplexing, caching, compression, redirects, error handling... etc. If you had to reinvent all of those on top of WebSockets (which is a very raw protocol), you’d end up with an HTTP/2 like protocol.
Could HTTP/2 have used WebSockets to act as it’s underlying transport layer? Possibly, but that’s an unnecessary extra level of abstraction (IP->TCP->WS->HTTP2->HTTP), not to mention that websockets are often established over HTTP initially. HTTP is big enough to have its own transport protocol so in fact they’ve gone the other way and specified WebSockets over HTTP/2.
Finally, it should also be noted that HTTP/2 does not make Web Sockets obselete either. They are different and with different advantages and disadvantages.

Why WebSockets use ("ws" and "wss") instead of ("http" and "https")?

What was a reason for registering special URI schemes: "ws" and "wss"?
I briefly read specs, and didn't find any reason about this change.
https://www.rfc-editor.org/rfc/rfc6455#section-11.1
WebSocket client sends special headers (Connection: Upgrade, Upgrade: websocket) which lets relatively easy decide whether this is normal HTTP requests (GET,POST ...etc) or this is WebSocket connection request.
Why WebSockets can't work using "http" and "https" schemes?
I wasn't on the board or anything, but here's any 2¢...:
The protocol's handshake currently uses HTTP(S) for connection establishment, but this is as far as the HTTP involvement goes.
It's highly possible that future versions might extend the handshake possibilities, using technologies such as ALPN.
By using the URI scheme ws://... and wss://..., the handshake is decoupled from the URI, allowing future changes to occur with less disturbance.
They use it for sake of architectural clarity, looks like there is no technical limitation why you could not handle your websocket connections using purely http.
Please notice javascript client libraries for handling websocket connections like Paho, are handling websockets purely over http protocol, and even fail if you are explicitly providing host prefixed with ws protocol instead - A piece of simple example from showcase code:
// Create a client instance
client = new Paho.MQTT.Client(
location.hostname, Number(location.port), "clientId"
);

Does HTTP/2 make websockets obsolete?

I'm learning about HTTP/2 protocol. It's a binary protocol with small message frames. It allows stream multiplexing over single TCP connection. Conceptually it seems very similar to WebSockets.
Are there plans to obsolete websockets and replace them with some kind of headerless HTTP/2 requests and server-initiated push messages? Or will WebSockets complement HTTP/2?
After just getting finished reading RFC 7540, HTTP/2 does obsolete websockets for all use cases except for pushing binary data from the server to a JS webclient. HTTP/2 fully supports binary bidi streaming (read on), but browser JS doesn't have an API for consuming binary data frames and AFAIK such an API is not planned.
For every other application of bidi streaming, HTTP/2 is as good or better than websockets, because (1) the spec does more work for you, and (2) in many cases it allows fewer TCP connections to be opened to an origin.
PUSH_PROMISE (colloquially known as server push) is not the issue here. That's just a performance optimization.
The main use case for Websockets in a browser is to enable bidirectional streaming of data. So, I think the OP's question becomes whether HTTP/2 does a better job of enabling bidirectional streaming in the browser, and I think that yes, it does.
First of all, it is bi-di. Just read the introduction to the streams section:
A "stream" is an independent, bidirectional sequence of frames
exchanged between the client and server within an HTTP/2 connection.
Streams have several important characteristics:
A single HTTP/2 connection can contain multiple concurrently open
streams, with either endpoint interleaving frames from multiple
streams.
Streams can be established and used unilaterally or shared by
either the client or server.
Streams can be closed by either endpoint.
Articles like this (linked in another answer) are wrong about this aspect of HTTP/2. They say it's not bidi. Look, there is one thing that can't happen with HTTP/2: After the connection is opened, the server can't initiate a regular stream, only a push stream. But once the client opens a stream by sending a request, both sides can send DATA frames across a persistent socket at any time - full bidi.
That's not much different from websockets: the client has to initiate a websocket upgrade request before the server can send data across, too.
The biggest difference is that, unlike websockets, HTTP/2 defines its own multiplexing semantics: how streams get identifiers and how frames carry the id of the stream they're on. HTTP/2 also defines flow control semantics for prioritizing streams. This is important in most real-world applications of bidi.
(That wrong article also says that the Websocket standard has multiplexing. No, it doesn't. It's not really hard to find that out, just open the Websocket RFC 6455 and press ⌘-F, and type "multiplex". After you read
The protocol is intended to be extensible; future versions will likely introduce additional concepts such as multiplexing.
You will find that there is 2013 draft extension for Websocket multiplexing. But I don't know which browsers, if any, support that. I wouldn't try to build my SPA webapp on the back of that extension, especially with HTTP/2 coming, the support may never arrive).
Multiplexing is exactly the kind of thing that you normally have to do yourself whenever you open up a websocket for bidi, say, to power a reactively updating single page app. I'm glad it's in the HTTP/2 spec, taken care of once and for all.
If you want to know what HTTP/2 can do, just look at gRPC. gRPC is implemented across HTTP/2. Look specifically at the half and full duplex streaming options that gRPC offers. (Note that gRPC doesn't currently work in browsers, but that is actually because browsers (1) don't expose the HTTP/2 frame to the client javascript, and (2) don't generally support Trailers, which are used in the gRPC spec.)
Where might websockets still have a place? The big one is server->browser pushed binary data. HTTP/2 does allow server->browser pushed binary data, but it isn't exposed in browser JS. For applications like pushing audio and video frames, this is a reason to use websockets.
Edit: Jan 17 2020
Over time this answer has gradually risen up to the top (which is good, because this answer is more-or-less correct). However there are still occasional comments saying that it is not correct for various reasons, usually related to some confusion about PUSH_PROMISE or how to actually consume message-oriented server -> client push in a single page app.
If you need to build a real-time chat app, let's say, where you need to broadcast new chat messages to all the clients in the chat room that have open connections, you can (and probably should) do this without websockets.
You would use Server-Sent Events to push messages down and the Fetch api to send requests up. Server-Sent Events (SSE) is a little-known but well supported API that exposes a message-oriented server-to-client stream. Although it doesn't look like it to the client JavaScript, under the hood your browser (if it supports HTTP/2) will reuse a single TCP connection to multiplex all of those messages. There is no efficiency loss and in fact it's a gain over websockets because all the other requests on your page are also sharing that same TCP connection. Need multiple streams? Open multiple EventSources! They'll be automatically multiplexed for you.
Besides being more resource efficient and having less initial latency than a websocket handshake, Server-Sent Events have the nice property that they automatically fall back and work over HTTP/1.1. But when you have an HTTP/2 connection they work incredibly well.
Here's a good article with a real-world example of accomplishing the reactively-updating SPA.
From what I understood HTTP/2 is not a replacement for websocket but aims to standardize SPDY protocol.
In HTTP/2, server-push is used behind the scene to improve resource loading by the client from the browser. As a developer, you don't really care about it during your development. However, with Websocket, the developer is allowed to use API which is able to consume and push message with an unique full-duplex connection.
These are not the same things, and they should complement each other.
I say Nay (Websockets aren't obsolete).
The first and most often ignored issue is that HTTP/2 push isn't enforceable and might be ignored by proxies, routers, other intermediaries or even the browser.
i.e. (from the HTTP2 draft):
An intermediary can receive pushes from the server and choose not to forward them on to the client. In other words, how to make use of the pushed information is up to that intermediary. Equally, the intermediary might choose to make additional pushes to the client, without any action taken by the server.
Hence, HTTP/2 Push can't replace WebSockets.
Also, HTTP/2 connections do close after a while.
It's true that the standard states that:
HTTP/2 connections are persistent. For best performance, it is expected that clients will not close connections until it is determined that no further communication with a server is necessary (for example, when a user navigates away from a particular web page) or until the server closes the connection.
But...
Servers are encouraged to maintain open connections for as long as possible but are permitted to terminate idle connections if necessary. When either endpoint chooses to close the transport-layer TCP connection, the terminating endpoint SHOULD first send a GOAWAY (Section 6.8) frame so that both endpoints can reliably determine whether previously sent frames have been processed and gracefully complete or terminate any necessary remaining tasks.
Even if the same connection allows for pushing content while it is open and even if HTTP/2 resolves some of the performance issues introduced by HTTP/1.1's 'keep-alive'... HTTP/2 connections aren't kept open indefinitely.
Nor can a webpage re-initiate an HTTP/2 connection once closed (unless we're back to long-pulling, that is).
EDIT (2017, two years later)
Implementations of HTTP/2 show that multiple browser tabs/windows share a single HTTP/2 connection, meaning that push will never know which tab / window it belongs to, eliminating the use of push as a replacement for Websockets.
EDIT (2020)
I'm not sure why people started downvoting the answer. If anything, the years since the answer was initially posted proved that HTTP/2 can't replace WebSockets and wasn't designed to do so.
Granted, HTTP/2 might be used to tunnel WebSocket connections, but these tunneled connections will still require the WebSocket protocol and they will effect the way the HTTP/2 container behaves.
The answer is no. The goal between the two are very different. There is even an RFC for WebSocket over HTTP/2 which allows you to make multiple WebSocket connections over a single HTTP/2 TCP pipe.
WS over HTTP/2 will be a resource conservation play by decreasing the time to open new connections and allowing for more communication channels without the added expense of more sockets, soft IRQs, and buffers.
https://datatracker.ietf.org/doc/html/draft-hirano-httpbis-websocket-over-http2-01
Well, to quote from this InfoQ article:
Well, the answer is clearly no, for a simple reason: As we have seen above, HTTP/2 introduces Server Push which enables the server to proactively send resources to the client cache. It does not, however, allow for pushing data down to the client application itself. Server pushes are only processed by the browser and do not pop up to the application code, meaning there is no API for the application to get notifications for those events.
And so HTTP2 push is really something between your browser and server, while Websockets really expose the APIs that can be used by both client (javascript, if its running on browser) and application code (running on server) for transferring real time data.
As of today, no.
HTTP/2, compared to HTTP, allows you to maintain a connection with a server. From there, you can have multiple streams of data at the same time. The intent is that you can push multiple things at the same time even without the client requesting it. For example, when a browser asks for a index.html, the server might want to also push index.css and index.js. The browser didn't ask for it, but the server might provide it without being asked because it can assume you're going to want in a few seconds.
This is faster than the HTTP/1 alternative of getting index.html, parsing it, discovering it needs index.js and index.css and then building 2 other requests for those files. HTTP/2 lets the server push data the client hasn't even asked for.
In that context, it's similar to WebSocket, but not really by design. WebSocket is supposed to allow a bi-directional communication similar to a TCP connection, or a serial connection. It's a socket where both communicate with each other. Also, the major difference is that you can send any arbitrary data packets in raw bytes, not encapsulated in HTTP protocol. The concepts of headers, paths, query strings only happen during the handshake, but WebSocket opens up a data stream.
The other difference is you get a lot more fine-tuned access to WebSocket in Javascript, whereas with HTTP, it's handled by the browser. All you get with HTTP is whatever you can fit in XHR/fetch(). That also means the browser will get to intercept and modify HTTP headers without you being able to control it (eg: Origin, Cookies, etc). Also, what HTTP/2 is able to push is sent to the browser. That means JS doesn't always (if ever) know things are being pushed. Again, it makes sense for index.css and index.js because the browser will cache it, but not so much for data packets.
It's really all in the name. HTTP stands for HyperText Transfer Protocol. We're geared around the concept of transferring assets. WebSocket is about building a socket connection where binary data gets passed around bidirectionally.
The one we're not really discussing is SSE (Server-Sent Events). Pushing data to the application (JS) isn't HTTP/2's intent, but it is for SSE. SSE gets really strengthened with HTTP/2. But it's a not a real replacement for WebSockets when what's important is the data itself, not the variable endpoints being reached. For each endpoint in with WebSocket a new data stream is created, but with SSE it's shared between the already existing HTTP/2 session.
Summarized here are the objectives for each:
HTTP - Respond to a request with one asset
HTTP/2 - Respond to a request with multiple assets
SSE - Respond with a unidirectional text (UTF-8) event stream
WebSocket - Create a bidirectional binary data stream
Message exchange and simple streaming(not audio, video streaming) can be done via both Http/2 multiplexing and WebSockets. So there is some overlap, but WebSockets have well established protocol, a lot of frameworks/APIs and less headers overhead.
Here is nice article about the topic.
No, WebSockets are not obsolete. However, HTTP/2 breaks websockets as defined for HTTP/1.1 (mostly by forbidding protocol updates using the Upgrade header). Which is why this rfc:
https://datatracker.ietf.org/doc/html/rfc8441
defines a websocket bootstrapping procedure for HTTP/2.
For the time being April 2020, HTTP/2 is not making WebSockets obsolete. The greatest advantage of WebSockets over HTTP2 is that
HTTP/2 works only on Browser Level not Application Level
Means that HTTP/2 does not offer any JS API like WebSockets to allow communication and transfer some kind of JSON or other data to server directly from Application (e.g. Website). So, as far as I believe, HTTP/2 will only make WebSockets obsolete if it starts offering API like WebSockets to talk to server. Till that it is just updated and faster version of HTTP 1.1.
No HTTP/2 does not make websockets obsolete, but SSE over HTTP/2 offers a viable alternative. The minor caveat is that SSE does not support unsolicited events from server to client (and neither does HTTP/2): i.e. the client has to explicitly subscribe by creating an EventSource instance specifying the event source endpoint. So you may have to slightly reorganise how the client arranges for events to be delivered - I can't think of a scenario where this is actually a technical barrier.
SSE works with HTTP/1.1. But HTTP/2 makes using SSE generally viable and competitive with websockets in terms of efficiency, instead of practically unusable in the case of HTTP/1.1. Firstly, HTTP/2 multiplexes many event source connections (or rather "streams" in HTTP/2 terms) onto a single TCP connection where as in HTTP/1.1 you'd need one connection for each. According to the HTTP/2 spec, millions of streams can be created per connection by default with the recommended (configurable) minimum being 100, where as browsers maybe severly limited in the number of TCP connections they can make. Second reason is efficiency: many streams in HTTP/2 is requires much less overhead than the many connections required in HTTP/1.1.
One final thing is, if you want to replace websockets with SSE your forgoing some of the tools / middlewares built on top of websockets. In particular I'm thinking of socket.io (which is how a lot of people actually use websockets), but I'm sure there is a ton more.

WebSockets protocol vs HTTP

There are many blogs and discussions about WebSocket and HTTP, and many developers and sites strongly advocate WebSockets, but I still can not understand why.
For example (arguments of WebSocket lovers):
HTML5 Web Sockets represents the next evolution of web communications—a full-duplex, bidirectional communications channel that operates through a single socket over the Web. - websocket.org
HTTP supports streaming: request body streaming(you are using it while uploading large files) and response body streaming.
During making the connection with WebSocket, client, and server exchange data per frame which is 2 bytes each, compared to 8 kilobytes of HTTP header when you do continuous polling.
Why do that 2 bytes not include TCP and under TCP protocols overhead?
GET /about.html HTTP/1.1
Host: example.org
This is ~48 bytes HTTP header.
HTTP chunked encoding - Chunked transfer encoding:
23
This is the data in the first chunk
1A
and this is the second one
3
con
8
sequence
0
So, the overhead per each chunk is not big.
Also, both protocols work over TCP, so all TCP issues with long-live connections are still there.
Questions:
Why is the WebSockets protocol better?
Why was it implemented instead of updating the HTTP protocol?
1) Why is the WebSockets protocol better?
WebSockets is better for situations that involve low-latency communication especially for low latency for client to server messages. For server to client data you can get fairly low latency using long-held connections and chunked transfer. However, this doesn't help with client to server latency which requires a new connection to be established for each client to server message.
Your 48 byte HTTP handshake is not realistic for real-world HTTP browser connections where there is often several kilobytes of data sent as part of the request (in both directions) including many headers and cookie data. Here is an example of a request/response to using Chrome:
Example request (2800 bytes including cookie data, 490 bytes without cookie data):
GET / HTTP/1.1
Host: www.cnn.com
Connection: keep-alive
Cache-Control: no-cache
Pragma: no-cache
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.68 Safari/537.17
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
Cookie: [[[2428 byte of cookie data]]]
Example response (355 bytes):
HTTP/1.1 200 OK
Server: nginx
Date: Wed, 13 Feb 2013 18:56:27 GMT
Content-Type: text/html
Transfer-Encoding: chunked
Connection: keep-alive
Set-Cookie: CG=US:TX:Arlington; path=/
Last-Modified: Wed, 13 Feb 2013 18:55:22 GMT
Vary: Accept-Encoding
Cache-Control: max-age=60, private
Expires: Wed, 13 Feb 2013 18:56:54 GMT
Content-Encoding: gzip
Both HTTP and WebSockets have equivalent sized initial connection handshakes, but with a WebSocket connection the initial handshake is performed once and then small messages only have 6 bytes of overhead (2 for the header and 4 for the mask value). The latency overhead is not so much from the size of the headers, but from the logic to parse/handle/store those headers. In addition, the TCP connection setup latency is probably a bigger factor than the size or processing time for each request.
2) Why was it implemented instead of updating HTTP protocol?
There are efforts to re-engineer the HTTP protocol to achieve better performance and lower latency such as SPDY, HTTP 2.0 and QUIC. This will improve the situation for normal HTTP requests, but it is likely that WebSockets and/or WebRTC DataChannel will still have lower latency for client to server data transfer than HTTP protocol (or it will be used in a mode that looks a lot like WebSockets anyways).
Update:
Here is a framework for thinking about web protocols:
TCP: low-level, bi-directional, full-duplex, and guaranteed order transport layer. No browser support (except via plugin/Flash).
HTTP 1.0: request-response transport protocol layered on TCP. The client makes one full request, the server gives one full response, and then the connection is closed. The request methods (GET, POST, HEAD) have specific transactional meaning for resources on the server.
HTTP 1.1: maintains the request-response nature of HTTP 1.0, but allows the connection to stay open for multiple full requests/full responses (one response per request). Still has full headers in the request and response but the connection is re-used and not closed. HTTP 1.1 also added some additional request methods (OPTIONS, PUT, DELETE, TRACE, CONNECT) which also have specific transactional meanings. However, as noted in the introduction to the HTTP 2.0 draft proposal, HTTP 1.1 pipelining is not widely deployed so this greatly limits the utility of HTTP 1.1 to solve latency between browsers and servers.
Long-poll: sort of a "hack" to HTTP (either 1.0 or 1.1) where the server does not respond immediately (or only responds partially with headers) to the client request. After a server response, the client immediately sends a new request (using the same connection if over HTTP 1.1).
HTTP streaming: a variety of techniques (multipart/chunked response) that allow the server to send more than one response to a single client request. The W3C is standardizing this as Server-Sent Events using a text/event-stream MIME type. The browser API (which is fairly similar to the WebSocket API) is called the EventSource API.
Comet/server push: this is an umbrella term that includes both long-poll and HTTP streaming. Comet libraries usually support multiple techniques to try and maximize cross-browser and cross-server support.
WebSockets: a transport layer built-on TCP that uses an HTTP friendly Upgrade handshake. Unlike TCP, which is a streaming transport, WebSockets is a message based transport: messages are delimited on the wire and are re-assembled in-full before delivery to the application. WebSocket connections are bi-directional, full-duplex and long-lived. After the initial handshake request/response, there is no transactional semantics and there is very little per message overhead. The client and server may send messages at any time and must handle message receipt asynchronously.
SPDY: a Google initiated proposal to extend HTTP using a more efficient wire protocol but maintaining all HTTP semantics (request/response, cookies, encoding). SPDY introduces a new framing format (with length-prefixed frames) and specifies a way to layering HTTP request/response pairs onto the new framing layer. Headers can be compressed and new headers can be sent after the connection has been established. There are real world implementations of SPDY in browsers and servers.
HTTP 2.0: has similar goals to SPDY: reduce HTTP latency and overhead while preserving HTTP semantics. The current draft is derived from SPDY and defines an upgrade handshake and data framing that is very similar the the WebSocket standard for handshake and framing. An alternate HTTP 2.0 draft proposal (httpbis-speed-mobility) actually uses WebSockets for the transport layer and adds the SPDY multiplexing and HTTP mapping as an WebSocket extension (WebSocket extensions are negotiated during the handshake).
WebRTC/CU-WebRTC: proposals to allow peer-to-peer connectivity between browsers. This may enable lower average and maximum latency communication because as the underlying transport is SDP/datagram rather than TCP. This allows out-of-order delivery of packets/messages which avoids the TCP issue of latency spikes caused by dropped packets which delay delivery of all subsequent packets (to guarantee in-order delivery).
QUIC: is an experimental protocol aimed at reducing web latency over that of TCP. On the surface, QUIC is very similar to TCP+TLS+SPDY implemented on UDP. QUIC provides multiplexing and flow control equivalent to HTTP/2, security equivalent to TLS, and connection semantics, reliability, and congestion control equivalentto TCP. Because TCP is implemented in operating system kernels, and middlebox firmware, making significant changes to TCP is next to impossible. However, since QUIC is built on top of UDP, it suffers from no such limitations. QUIC is designed and optimised for HTTP/2 semantics.
References:
HTTP:
Wikipedia HTTP Page
W3C List of HTTP related Drafts/Protocols
List of IETF HTTP/1.1 and HTTP/2.0 Drafts
Server-Sent Event:
W3C Server-Sent Events/EventSource Candidate Recommendation
W3C Server-Sent Events/EventSource Draft
WebSockets:
IETF RFC 6455 WebSockets Protocol
IETF RFC 6455 WebSocket Errata
SPDY:
IETF SPDY Draft
HTTP 2.0:
IETF HTTP 2.0 httpbis-http2 Draft
IETF HTTP 2.0 httpbis-speed-mobility Draft
IETF httpbis-network-friendly Draft - an older HTTP 2.0 related proposal
WebRTC:
W3C WebRTC API Draft
List of IETF WebRTC Drafts
IETF WebRTC Overview Draft
IETF WebRTC DataChannel Draft
Microsoft CU-WebRTC Proposal Start Page
QUIC:
QUIC Chrominum Project
IETF QUIC Draft
You seem to assume that WebSocket is a replacement for HTTP. It is not. It's an extension.
The main use-case of WebSockets are Javascript applications which run in the web browser and receive real-time data from a server. Games are a good example.
Before WebSockets, the only method for JavaScript applications to interact with a server was through XmlHttpRequest. But these have a major disadvantage: The server can't send data unless the client has explicitly requested it.
But the new WebSocket feature allows the server to send data whenever it wants. This allows to implement browser-based games with a much lower latency and without having to use ugly hacks like AJAX long-polling or browser plugins.
So why not use normal HTTP with streamed requests and responses
In a comment to another answer you suggested to just stream the client request and response body asynchronously.
In fact, WebSockets are basically that. An attempt to open a WebSocket connection from the client looks like a HTTP request at first, but a special directive in the header (Upgrade: websocket) tells the server to start communicating in this asynchronous mode. First drafts of the WebSocket protocol weren't much more than that and some handshaking to ensure that the server actually understands that the client wants to communicate asynchronously. But then it was realized that proxy servers would be confused by that, because they are used to the usual request/response model of HTTP. A potential attack scenario against proxy servers was discovered. To prevent this it was necessary to make WebSocket traffic look unlike any normal HTTP traffic. That's why the masking keys were introduced in the final version of the protocol.
A regular REST API uses HTTP as the underlying protocol for communication, which follows the request and response paradigm, meaning the communication involves the client requesting some data or resource from a server, and the server responding back to that client. However, HTTP is a stateless protocol, so every request-response cycle will end up having to repeat the header and metadata information. This incurs additional latency in case of frequently repeated request-response cycles.
With WebSockets, although the communication still starts off as an initial HTTP handshake, it is further upgraded to follow the WebSockets protocol (i.e. if both the server and the client are compliant with the protocol as not all entities support the WebSockets protocol).
Now with WebSockets, it is possible to establish a full-duplex and persistent connection between the client and a server. This means that unlike a request and a response, the connection stays open for as long as the application is running (i.e. it’s persistent), and since it is full-duplex, two-way simultaneous communication is possible i.e now the server is capable of initiating communication and 'push' some data to the client when new data (that the client is interested in) becomes available.
The WebSockets protocol is stateful and allows you to implement the Publish-Subscribe (or Pub/Sub) messaging pattern which is the primary concept used in the real-time technologies where you are able to get new updates in the form of server push without the client having to request (refresh the page) repeatedly. Examples of such applications are Uber car's location tracking, Push Notifications, Stock market prices updating in real-time, chat, multiplayer games, live online collaboration tools, etc.
You can check out a deep dive article on Websockets which explains the history of this protocol, how it came into being, what it’s used for and how you can implement it yourself.
Here's a video from a presentation I did about WebSockets and how they are different from using the regular REST APIs: Standardisation and leveraging the exponential rise in data streaming
For the TL;DR, here are 2 cents and a simpler version for your questions:
WebSockets provides these benefits over HTTP:
Persistent stateful connection for the duration of the connection
Low latency: near-real-time communication between server/client due to no overhead of reestablishing connections for each request as HTTP requires.
Full duplex: both server and client can send/receive simultaneously
WebSocket and HTTP protocol have been designed to solve different problems, I.E. WebSocket was designed to improve bi-directional communication whereas HTTP was designed to be stateless, distributed using a request/response model. Other than sharing the ports for legacy reasons (firewall/proxy penetration), there isn't much common ground to combine them into one protocol.
Why is the WebSockets protocol better?
I don't think we can compare them side by side like who is better. That won't be a fair comparison simply because they are solving two different problems. Their requirements are different. It will be like comparing apples to oranges. They are different.
HTTP is a request-response protocol. The client (browser) wants something, the server gives it. That is. If what the data client wants is big, the server might send streaming data to avoid unwanted buffer problems. Here the main requirement or problem is how to make the request from clients and how to response the resources(hypertext) they request. That is where HTTP shine.
In HTTP, only client requests. The server only responds.
WebSocket is not a request-response protocol where only the client can request. It is a socket(very similar to TCP socket). Mean once the connection is open, either side can send data until the underlining TCP connection is closed. It is just like a normal socket. The only difference with TCP socket is WebSocket can be used on the web. On the web, we have many restrictions on a normal socket. Most firewalls will block other ports than 80 and 433 that HTTP used. Proxies and intermediaries will be problematic as well. So to make the protocol easier to deploy to existing infrastructures WebSocket use HTTP handshake to upgrade. That means when the first time connection is going to open, the client sent an HTTP request to tell the server saying "That is not HTTP request, please upgrade to WebSocket protocol".
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Once the server understands the request and upgraded to WebSocket protocol, none of the HTTP protocols applied anymore.
So my answer is Neither one is better than each other. They are completely different.
Why was it implemented instead of updating the HTTP protocol?
Well, we can make everything under the name called HTTP as well. But shall we? If they are two different things, I will prefer two different names. So do Hickson and Michael Carter .
The other answers do not seem to touch on a key aspect here, and that is you make no mention of requiring supporting a web browser as a client. Most of the limitations of plain HTTP above are assuming you would be working with browser/ JS implementations.
The HTTP protocol is fully capable of full-duplex communication; it is legal to have a client perform a POST with a chunked encoding transfer, and a server to return a response with a chunked-encoding body. This would remove the header overhead to just at init time.
So if all you're looking for is full-duplex, control both client and server, and are not interested in extra framing/features of WebSockets, then I would argue that HTTP is a simpler approach with lower latency/CPU (although the latency would really only differ in microseconds or less for either).

SPDY as replacement for Websockets?

First off - I understand SPDY and Websockets aren't the same thing, and that you can run Websockets over SPDY like you can with HTTP, etc.
However - I am wondering if SPDY would be a viable replacement for websockets if I am trying to provide a REST (like) API that also supports server push (bi-directional calls over the same connection).
My current prototype uses websockets (node+socket.io), and works fine. However, my issue with websockets is I am having to dream up my own JSON protocol for routing requests both to and from the server. I'd much rather use REST-style URIs and Headers in requests, which fits better in a REST-based architecture. SPDY seems like it would support this better.
Also, because of the lack of headers, I'm concerned websockets won't fit well in our deployment network, and thinking SPDY would be a better fit again.
However, I've not seen many examples of bidirectional SPDY requests, apart from pushing files to the browser. I would like to push events and data to the browsers, such as:
Content-Type: application/json
{
"id": "ca823f3e233233",
"name": "Greg Brady"
}
but it's not clear to me how the browser/Javascript might "listen" and react to these, as I would with the WebSocket and socket.io APIs.
Let's start from the beginning: why would you want to run WebSockets over SPDY, as opposed to doing an HTTP upgrade? If you upgrade an HTTP connection to WS, then nothing else can use that TCP stream - the WS connection can be idle, but the connection is blocked nonetheless. With SPDY, you can mux multiple requests/responses, and a websocket connection (or even multiple) over the same underlying TCP stream. On a practical note, as of July 2012, WS over SPDY is still a work in progress, so you will have to wait to use SPDY for WebSockets - hopefully not too long though!
But let's assume the support is there... The reason why it's not clear how to listen for "SPDY Push" from JavaScript is because there is no way to do that! A pushed resource goes into your browsers cache - nothing more, nothing less. If you need to stream data to your javascript callbacks, then WebSockets, or Server-Sent Events (SSE) is the answer.
So, putting it all together:
HTTP adds a lot of overhead for individual small requests (headers, etc)
WebSockets gives you a low overhead channel, but requires you implement own routing
SPDY will significantly reduce the overhead and cost of small HTTP requests (win)
SSE is a good, simple alternative to pushing data to the client (which works today, over SPDY)
You could use SPDY+SSE to meet your goals, and all of that communication can run over the same TCP channel. SPDY requests to the server, SSE push from the server.
First some clarifications:
The base WebSocket protocol (IETF 6455) is not layered onto HTTP. The initial handshake for WebSocket connections is HTTP compatible, but once the handshake is completed, the protocol is a framed, bi-directional full-duplex connection with very low overhead (often just 2 bytes per frame of header).
The WebSocket over SPDY idea is a proposal that may or may not see the light of day. In this case, WebSocket is in fact being layered on SPDY. The initial connection/handshake may happen faster due to the nature of SPDY versus HTTP, however, the data frames will have more overhead because the WebSocket header fields are mapped into SPDY header fields.
SPDY aims to be a more efficient replacement for HTTP. WebSocket is an entirely different beast that enables very low-latency bi-directional/full-duplex messaging between the client and server.
If what you are interested in server-push with a simple API and you don't need super low-latency, then you might consider server-sent events which has an API that is simple and similar to the WebSocket API. Or you could look into one of the many good Comet libraries which enable server-push but will better support old browsers unlike any of the above solutions.
However, my issue with websockets is I am having to dream up my own
JSON protocol for routing requests both to and from the server.
I wrote a thin RPC layer over socket.io wrapping network calls in promises just for that reason. You can take a peek at it here.

Resources