Fundamentals 28 min read

Web Protocol Deep Dive: Chrome Network Panel, Connection Keep-Alive, Head‑of‑Line Blocking, and HTTP Body Transfer

The series teaches mobile developers how to use Chrome’s Network panel and Wireshark, explains connection keep-alive, demonstrates HTTP 1.x head-of-line blocking with Go and OkHttp, and clarifies fixed-length versus chunked body transfer, providing practical code and traffic analysis for deeper protocol understanding.

vivo Internet Technology
vivo Internet Technology
vivo Internet Technology
Web Protocol Deep Dive: Chrome Network Panel, Connection Keep-Alive, Head‑of‑Line Blocking, and HTTP Body Transfer

This article series was created to fill gaps the author encountered while learning large‑scale front‑end development, especially around web protocols. The author previously only used tools like Charles to capture packets and lacked a solid understanding of HTTP, HTTPS, caching headers, and mobile‑side network optimization.

Motivation points include:

Limited knowledge of HTTP beyond packet capture.

Superficial grasp of TLS/SSL and encryption.

Insufficient understanding of H5 cache directives.

Difficulty reading deep‑network‑optimization articles for mobile.

Inability to argue for better technical solutions when proposing mobile architectures.

Reliance on front‑end engineers for troubleshooting web‑loading issues on mobile.

Lack of hands‑on experience writing server‑side code to truly understand protocols.

No comparison between browser and Android OkHttp network behavior.

OkHttp articles often ignore the actual HTTP protocol implementation.

The series uses Go for all server‑side examples and Wireshark for packet capture, focusing on practical code and real traffic rather than theory.

The content is divided into four main parts:

Chrome Network Panel Usage – Demonstrates how a mobile developer can use Chrome’s Network tab to diagnose H5 issues. It explains disabling cache, simulating weak networks (e.g., Fast 3G), using filters like is:from-cache , large-than: , and visualizing request‑dependency relationships (blue request → green upstream request). Screenshots illustrate the UI and the effect of these settings on page load time.

Connection Keep‑Alive – Describes how modern client‑server communication often passes through multiple proxy layers (firewall, load‑balancer, routing). It explains the X‑Forwarded‑For and X‑Real‑IP headers, shows how Nginx works (master‑worker model, single‑threaded I/O multiplexing), and introduces OpenResty as an extensible Lua‑based alternative to Nginx.

HTTP Head‑of‑Line Blocking (HOLB) – Provides a series of experiments to clarify the nature of HOLB in HTTP 1.x. A Go server exposing /slow (10 s delay) and /fast (5 s delay) endpoints is written (see code block below). An Android OkHttp client is configured to use a single TCP connection per host and to send requests asynchronously via enqueue . Wireshark captures show that with a single connection the fast request waits for the slow response, while increasing the per‑host connection limit to 5 allows parallel requests on separate TCP streams. The author concludes that HOLB is primarily an application‑layer limitation enforced by the client, and that browsers mitigate it by opening up to six concurrent connections per domain.

HTTP Body Transfer – Explains the difference between fixed‑length (Content‑Length) and chunked transfer encoding (hexadecimal chunk sizes). A Go Echo server that streams a response using Write and Flush demonstrates chunked output (code block below). The article also shows a simple HTML form for file upload, the corresponding Go handler that processes multipart/form‑data, and an OkHttp multipart request (code block below). Wireshark screenshots illustrate the raw HTTP exchange, including the Content‑Disposition header.

Key code examples (preserved in tags):

package main

import (
    "io"
    "net/http"
    "os"
    "time"
    "github.com/labstack/echo"
)

func main() {
    e := echo.New()
    e.GET("/slow", slowRes)
    e.GET("/fast", fastRes)
    e.Logger.Fatal(e.Start(":1329"))
}

func fastRes(c echo.Context) error {
    println("get fast request!!!!!")
    time.Sleep(5 * time.Second)
    return c.String(http.StatusOK, "fast reponse")
}

func slowRes(c echo.Context) error {
    println("get slow request!!!!!")
    time.Sleep(10 * time.Second)
    return c.String(http.StatusOK, "slow reponse")
}
dispatcher = new Dispatcher();
dispatcher.setMaxRequestsPerHost(1);
client = new OkHttpClient.Builder()
    .connectTimeout(20, TimeUnit.SECONDS)
    .readTimeout(20, TimeUnit.SECONDS)
    .dispatcher(dispatcher)
    .build();

new Thread() {
    @Override public void run() {
        Request request = new Request.Builder().get().url("http://www.dailyreport.ltd:1329/slow").build();
        client.newCall(request).enqueue(new Callback() { ... });
    }
}.start();

new Thread() {
    @Override public void run() {
        Thread.sleep(2000);
        Request request = new Request.Builder().get().url("http://www.dailyreport.ltd:1329/fast").build();
        client.newCall(request).enqueue(new Callback() { ... });
    }
}.start();
package main

import (
    "net/http"
    "github.com/labstack/echo"
)

func main() {
    e := echo.New()
    // chunked transfer without fixed length
    e.GET("/", func(c echo.Context) error {
        c.Response().WriteHeader(http.StatusOK)
        c.Response().Write([]byte("hello"))
        c.Response().Flush()
        c.Response().Write([]byte("wuyue"))
        c.Response().Flush()
        return nil
    })
    e.Logger.Fatal(e.Start(":1323"))
}
// Multipart upload example with intentional wrong content types
RequestBody requestBody1 = RequestBody.create(MediaType.parse("image/gifccc"), new File("/mnt/sdcard/ccc.txt"));
RequestBody requestBody2 = RequestBody.create(MediaType.parse("text/plain111"), new File("/mnt/sdcard/Gif.gif"));
RequestBody requestBody = new MultipartBody.Builder()
    .setType(MultipartBody.FORM)
    .addFormDataPart("file2", "Gif.gif", requestBody1)
    .addFormDataPart("file", "ccc.txt", requestBody2)
    .addFormDataPart("name", "吴越")
    .build();
Request request = new Request.Builder().url("http://47.100.237.180:1329/uploadresult").post(requestBody).build();

The final section summarizes that the author has introduced practical usage of Chrome’s Network panel and Wireshark for HTTP analysis, clarified the concept of head‑of‑line blocking in HTTP 1.x, and outlined strategies such as increasing per‑domain connections or using multiple domains to improve page load speed. Upcoming chapters will cover caching, DNS, WebSocket, HTTP/2, and TLS in detail.

Mobile DevelopmentGoHTTPNetworkingOkHttpChrome NetworkWeb Protocols
vivo Internet Technology
Written by

vivo Internet Technology

Sharing practical vivo Internet technology insights and salon events, plus the latest industry news and hot conferences.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.