UPDATE (for anyone interested in the result :)
I could not understand why the following protocol is negotiated between chrome and the node-http2 server. My suspicion was a self-signed certificate or ALPN / NPN support issue. So I switched to golang HTTP / 2 implementation . The same setup works fine, and I see a single-negotiated TCP connection (chrome -> golang)
I read about HTTP / 2 and how it solves the latency problem using HTTP / 1.1 with one multiplexed TCP connection to one host, so I decided to try it.
Experiment
- created a simple html file with links to one css, one js and a couple of images.
- A simple HTTP server in Node.js that serves all these files.
- Used by chrome to create http request
- Used by tcptrack on Ubuntu ( tcptrack ) to monitor TCP connections created on the http server.
The tcptrack window shows 4 connections. Thus, the browser opens another connection for requesting image and css / js.

I get a similar output using tcpdump. The tcptrack command was used for reference.
tcptrack -d -i eth0 -r 3600 port 8989
and tcpdump also shows a similar output
tcpdump -i eth0 -nns 0 "dst port 8989 and tcp [tcpflags] == tcp-syn"
Simple all in one http server serving these files was something like below (corresponding code)
(function(){ ........... var server = http.createServer(function(request, response) { .......... fs.readFile(filetoRet, function (err,data) { if(filePath.indexOf(".jpg") >-1){ response.writeHead(200, {"Content-Type": "image/jpg"}); }..... response.write(data); response.end(); }); }); server.listen(8989); })()
After that I tried to use http / 2.
- Chrome flag enabled to send http / 2 request
- Created http / 2 server using node-http2
- A simple http server has the same code as http / 1.1, except that it uses the http2 server module installed in step 2.
- Made a request using chrome (it should have been an https inline request with the HTTP / 2 specification)
- Captured tcptrack / tcpdump output

So this still shows some TCP connections. Also, if I increase the number of images in html, the number of connections increases.
So I'm not sure how to read this. Is this how HTTP / 2 protocol should behave (or is it a chrome error)? Is there a better way to visualize HTTP / 2 profits with a simple http / 2 client server?
Note. I use a self-signed certificate for the HTTP / 2 server, so chrome gives a warning before going to the page, and maybe these closed connections represent it, but I donβt think this should affect how the page and its components are requested by the protocol
Thank you all for your patience in reading this and appreciate any suggestions.
msingh
PS: Wireshark TCP network capture is no different. It was just harder for me to isolate traffic in Wireshark, so we used tcpdump and tcptrack.
Update: update: Looking at chrome: // net-internals / HTTP / 2 request negotiation fails, and it reverts to using HTTP / 1.1. I donβt understand the reason yet.
Internal events of chrome show
t=879052 [st= 0] +HTTP_STREAM_JOB [dt=19] --> original_url = "https://msinghlinux.ads.com:8900/" --> priority = "HIGHEST" --> url = "https://msinghlinux.ads.com:8900/" t=879052 [st= 0] +PROXY_SERVICE [dt=0] t=879052 [st= 0] PROXY_SERVICE_RESOLVED_PROXY_LIST --> pac_string = "DIRECT" t=879052 [st= 0] -PROXY_SERVICE t=879052 [st= 0] +HOST_RESOLVER_IMPL_REQUEST [dt=0] --> address_family = 0 --> allow_cached_response = true --> host = "msinghlinux.ads.com:8900" --> is_speculative = false t=879052 [st= 0] HOST_RESOLVER_IMPL_CACHE_HIT t=879052 [st= 0] -HOST_RESOLVER_IMPL_REQUEST t=879052 [st= 0] +SOCKET_POOL [dt=19] t=879071 [st=19] SOCKET_POOL_BOUND_TO_CONNECT_JOB --> source_dependency = 26961 (CONNECT_JOB) t=879071 [st=19] SOCKET_POOL_BOUND_TO_SOCKET --> source_dependency = 26967 (SOCKET) t=879071 [st=19] -SOCKET_POOL t=879071 [st=19] HTTP_STREAM_REQUEST_PROTO --> next_proto_status = "negotiated" --> proto = "http/1.1" t=879071 [st=19] HTTP_STREAM_JOB_BOUND_TO_REQUEST --> source_dependency = 26910 (URL_REQUEST) t=879071 [st=19] -HTTP_STREAM_JOB
The value of the following protocol is http / 1.1 (next_proto_status and proto). But he does not say that he failed in the negotiations that caused this reserve? Could the reason for the self-signed certificate?
HTTP / 2 Server Code
var options = { key: fs.readFileSync('./server.key'), cert: fs.readFileSync('./server.crt') }; options.log = bunyan.createLogger(...); require('http2').createServer(options,function(request, response) { .... same code as http/1.1 server }).listen(8900);