4.3.25 · D3 · Coding › Computer Networks › HTTP - 2 — multiplexing, header compression (HPACK), server
Intuition Yeh page kya hai
Parent note ne tumhe HTTP/2 ke rules bataye. Yeh page tumse arithmetic karwati hai — ek real integer ko bit by bit encode karo, exact bytes count karo jo HPACK bachata hai, stream ID assignment walk karo, aur traps pakdo (zero, overflow, even/odd IDs, cache hits). Agar tum neeche diye matrix ka har cell work kar sako, toh tum wire samajhte ho, sirf buzzwords nahin.
Har symbol jo hum use karte hain woh zero se bana hai. Ek byte = 8 bits. Ek bit ek single 0 ya 1 hai. Jab hum 0b01010 likhte hain toh 0b ka matlab sirf yeh hai "aage aane wale digits ko binary mein padho". Shuru karne ke liye bas itna hi notation chahiye.
Definition Is page par use hone wali units: KiB vs KB
Classic binary-vs-decimal confusion se bachne ke liye, yeh page KiB (kibibyte) = 1024 bytes use karta hai, jo bilkul do ki power hai, kyunki networking byte counts aur windows naturally do ki powers hote hain. Hum kabhi bhi "KB" ambiguously nahin likhte. Jab tum "5 KiB" dekho toh uska matlab exactly 5 × 1024 = 5120 bytes hai.
Definition Prefix, prefix length
N , aur HPACK first byte
HPACK kabhi raw multi-byte integer nahin bhejta. Woh ek chhote integer ko ek byte ke low N bits mein pack karta hai, jiske high bits mein already flag bits hote hain . Woh flag bits already batate hain ki yeh kis type ka field hai (indexed? literal? etc.). Toh integer sirf bache hue N bits use kar sakta hai — yeh prefix hai, aur N prefix length hai.
"5-bit prefix" ka matlab: us byte ke top 8 − 5 = 3 bits flag bits hain, bottom 5 bits (integer ka start) hold karte hain.
"6-bit prefix" ka matlab: top 8 − 6 = 2 bits flag bits hain, bottom 6 bits integer hold karte hain.
"7-bit prefix" ka matlab: top par 1 flag bit, 7 bits integer ke liye.
Definition HPACK field types aur unke flag-bit patterns (kaun sa
N kaun use karta hai)
Har HPACK header field ek first byte se shuru hota hai jiske high flag bits representation pick karte hain , aur woh choice prefix length N fix kar deti hai. Is page par jo char types milte hain:
Representation
High flag bits
Prefix length N
Matlab
Indexed
1
7-bit
poora header = ek table index
Literal with incremental indexing
01
6-bit
naya header, dynamic table mein add karo
Literal without indexing
0000
4-bit
naya header, store mat karo
Dynamic table size update
001
5-bit
dynamic table resize karo
Toh jab Example 5 likhta hai "01 flag + a 6-bit name-index", toh 01 literal-with-incremental-indexing marker hai, aur kyunki woh marker top 2 bits kha leta hai, exactly N = 6 bits name index ke liye bache rehte hain. Flag bits → N ka mapping arbitrary nahin hai — yeh RFC 7541 spec se fixed hai taaki encoder aur decoder hamesha agree karein.
Definition Integer rule (yahi "prefix integer encoding" ka matlab hai)
Ek non-negative integer I ko N -bit prefix mein encode karne ke liye:
Agar I < 2 N − 1 : I ko directly N prefix bits mein rakho. Ho gaya (ek byte).
Warna: prefix mein 2 N − 1 (saare prefix bits = 1) rakho overflow marker ki tarah, phir I ′ = I − ( 2 N − 1 ) ko continuation bytes mein 7-bit groups mein emit karo (high bit set = "aur aane wala hai").
I hamesha ≥ 0 hota hai — invalid inputs ke baare mein neeche [!mistake] dekho ki negatives aur unbounded lengths kyun reject hote hain.
Common mistake "Koi bhi integer, including negatives ya arbitrarily large wale, prefix-encode ho sakte hain."
Kyun sahi lagta hai: continuation scheme dekh ke lagta hai yeh forever grow kar sakta hai. Fix: HPACK integers sirf non-negative hote hain — format mein kahin bhi sign bit nahin hai, toh negative I simply representable nahin hai (ek encoder jo try karta woh garbage produce karta). Aur decoders continuation bytes cap karna chahiye (RFC 7541 decoders ko aise integers reject karne ki requirement deta hai jo implementation ki limit se zyada ho jaayein, typically ek value jo defined field mein fit nahin ho) ek malicious peer ko rokne ke liye jo endless high-bit-set bytes bhej sakta hai — yeh denial-of-service hai. Toh valid domain 0 ≤ I ≤ I m a x hai, aur malformed inputs (negative, ya over-long continuation run) connection errors hain, numbers nahin.
Is topic ke har possible case class, aur kaun sa worked example usse cover karta hai:
Cell
Case class
Covered by
A
Prefix integer — chhoti value, prefix mein fit ho jaati hai
Example 1
B
Prefix integer — value continuation bytes mein overflow karti hai
Example 2
C
Boundary value I = 2 N − 1 (yeh "off by one" trap hai)
Example 3
D
Zero / degenerate input (I = 0 , empty header)
Example 4
E
HPACK byte-savings count repeated requests par
Example 5
F
Stream ID assignment — odd vs even, ordering
Example 6
G
Multiplexing interleave + TCP HOL limiting case
Example 7
H
Server push cache-hit vs wasted-push (real-world)
Example 8
I
Exam twist — raw bytes ko number mein decode karo
Example 9
J
Invalid / limiting — negative ya over-long integer
Upar [!mistake] dekho
I = 10 ko 5-bit prefix mein encode karo
Forecast: aage padhne se pehle andaza lagao — kya iske liye ek byte chahiye ya zyada? Sabse bada number kya hai jo 5-bit prefix directly hold kar sakta hai?
Steps:
Prefix limit 2 N − 1 compute karo N = 5 ke saath: 2 5 − 1 = 31 .
Yeh step kyun? Rule kehta hai: agar I < 2 N − 1 toh I ko directly N bits mein store karo. Toh pehle "prefix ki ceiling" jaanni zaroori hai. 31 sabse bada value hai jo 5 bits mein directly store ho sakta hai bina overflow trigger kiye.
Compare karo: kya 10 < 31 hai? Haan.
Yeh step kyun? Yeh poora branch decide karta hai. Kyunki 10 safely 31 se neeche hai, hum continuation bytes kabhi use nahin karenge.
10 ko 5 low bits mein binary mein likho: 10 = 8 + 2 = 0101 0 2 . Flag bits 000 ke saath poora byte 000 01010 hai.
Yeh step kyun? 5-bit field literally number hold karta hai. 3 high bits HPACK flag bits hain — yahan hum unhe 000 dikhate hain taaki tum poora byte dekho. (Ek "indexed" field mein top flag bit actually 1 hogi; baat yeh hai ki woh bits representation type ki hain, integer ki nahin.)
Answer: ek byte; prefix bits 01010, full byte 000 01010.
Verify: 01010 ko plain binary number ki tarah padhna: 0 ⋅ 16 + 1 ⋅ 8 + 0 ⋅ 4 + 1 ⋅ 2 + 0 ⋅ 1 = 10 . ✓ Input se match karta hai. Units check: ek index ek pure count hai, koi dimension nahin — theek hai.
I = 1337 ko 5-bit prefix mein encode karo
Forecast: 1337 bahut 31 se bada hai. Andaza lagao ki kitne bytes chahiye honge, aur pehle byte mein kya value hogi.
Steps:
2 5 − 1 = 31 . Kya 1337 < 31 hai? Nahin.
Yeh step kyun? Hum overflow branch mein jaate hain. Prefix number hold nahin kar sakta, toh uske 5 bits saare 1s ban jaate hain (marker), yaani pehla byte 000 11111 hai.
First byte prefix = 31 . Phir leftover compute karo I ′ = I − 31 = 1337 − 31 = 1306 .
Yeh step kyun? Prefix ne already 31 ki value "spend" kar di hai, toh continuation bytes ko sirf bacha hua carry karna hai. Yeh double-counting se bachata hai.
I ′ ko 7-bit groups mein emit karo, high bit = "aur bytes aane wale hain":
1306 ≥ 128 ? Haan. 1306 mod 128 = 26 . Emit 26 + 128 = 154 . Set I ′ ← ⌊ 1306/128 ⌋ = 10 .
10 ≥ 128 ? Nahin. Emit 10 (high bit clear — yeh last byte hai).
Yeh step kyun? Har continuation byte 7 real bits (0–127) plus 1 flag bit (128) pack karta hai. 7-bit chunks mein split karna exactly varint encoding hai — wahi trick jo protobuf aur QUIC use karte hain. High bit ek self-describing "continue?" flag hai toh decoder ko kabhi length field ki zaroorat nahin.
Answer: bytes 31, 154, 10 (pehle byte ki full form 000 11111).
Verify: decode karo: 31 + ( 154 − 128 ) + 10 ⋅ 128 = 31 + 26 + 1280 = 1337 . ✓ Input reconstruct ho gaya.
I = 31 ko 5-bit prefix mein encode karo (classic off-by-one)
Forecast: 31 = 2 5 − 1 . Dekh ke lagta hai yeh 5 bits mein fit ho jaayega. Kya hoga? Step 1 se pehle andaza lagao.
Steps:
Rule strict inequality use karta hai: directly store karo sirf tab agar I < 2 N − 1 . Yahan I = 31 aur 2 N − 1 = 31 , toh I < 31 false hai.
Yeh step kyun? Yahi trap hai. Agar hum naively 31 prefix mein store karte, toh decoder 11111 read karta aur sochta "prefix full hai, continuation bytes padho" — aur phir hamesha ke liye wait karta bytes ke liye jo kabhi aate hi nahin. Value 2 N − 1 reserved hai "overflow marker" ki tarah, toh ek genuine 31 bhi overflow karna padega.
First byte prefix = 31 (marker, full byte 000 11111). Leftover I ′ = 31 − 31 = 0 .
Yeh step kyun? Hum exactly ceiling par hain, toh kuch bhi leftover nahin hai.
Emit I ′ = 0 : kya 0 ≥ 128 hai? Nahin. Ek single byte 0 emit karo (high bit clear = last).
Yeh step kyun? Ek continuation byte carrying 0 decoder ko batata hai "overflow ne kuch add nahin kiya".
Answer: bytes 31, 0 (5 bits mein "fit" hone wali value ke liye do bytes!).
Verify: decode karo: 31 + 0 = 31 . ✓ Aur note karo yeh I = 31 + 128 = 159 se ambiguous nahin hai, jo 31, 128, 1 encode hota. Reserved marker har value ko uniquely decodable rakhta hai.
I = 0 ko 5-bit prefix mein encode karo, aur ek empty header value encode karo
Forecast: sabse chhoti possible encoding kya hai? Kya ek header value zero characters lamba ho sakta hai?
Steps:
I = 0 : kya 0 < 31 hai? Haan → directly store karo. Prefix bits 00000, full byte 000 00000.
Yeh step kyun? Zero ek bilkul valid index/count hai; yeh trivially fit ho jaata hai. Yeh sabse chhota case hai — poore system ka base. (Yeh bhi confirm karta hai I ≥ 0 : zero valid domain ka floor hai.)
Ek empty header value (ek header jiska value empty string hai, e.g. ek bare flag header): uski length 0 hai. HPACK 0 ka length prefix likhta hai aur phir koi value bytes nahin.
Yeh step kyun? Length-prefixing ka matlab "exactly L bytes padho". L = 0 ke saath kuch nahin padhna. Yahi reason hai ki HPACK ko kabhi terminator character ki zaroorat nahin — length 0 unambiguous hai.
Answer: I = 0 → byte 000 00000 (=0); empty value → single length byte 0, zero value bytes.
Verify: 00000 decode karo = 0 . ✓ Length 0 decode karo ⇒ 0 bytes padho ⇒ empty string. ✓ Degenerate case well-defined hai, koi crash nahin.
cookie header jiska value 200 bytes hai, 100 requests par bheja gaya — exact bytes, HPACK vs raw?
Forecast: raw HTTP/1.1 har baar poora cookie dobara bhejta hai. Total guess karo, phir HPACK ka total guess karo. Ratio tumhe surprise karega.
Cookie value V = 200 bytes, R = 100 requests par. Ab hum har overhead byte count karenge, estimate nahin.
Steps:
Raw value bytes per send: hum sirf cookie ke value bytes V = 200 count karte hain fair comparison ke liye (dono schemes unhe carry karte hain). Raw HTTP/1.1 unhe har baar dobara bhejta hai:
raw = V × R = 200 × 100 = 20000 bytes .
Yeh step kyun? HTTP/1.1 headers plain text hain jo verbatim dobara bheje jaate hain — requests ke beech koi memory nahin, toh 100 requests mein se har ek poore 200 bytes pay karta hai.
HPACK request 1 (literal with incremental indexing) — har field count karo:
1 byte: pehla byte. Uske top 2 bits 01 flag hain (yeh literal-with-incremental-indexing representation hai — upar field-types table dekho), jo name index ke liye 6-bit prefix chhod deta hai. Static-table cookie name index 32 par hai, aur 32 < 2 6 − 1 = 63 , toh index 32 directly un 6 bits mein fit ho jaata hai → 1 byte .
1 byte: value length prefix — ek 7-bit prefix integer holding 200 . Kyunki 200 ≥ 2 7 − 1 = 127 , iske actually 2 bytes lagte hain: marker 127 , phir 200 − 127 = 73 . Toh length ke liye 2 bytes .
200 bytes: literal value itself (assume karo Huffman shrink nahin, worst case).
Total request 1 = 1 + 2 + 200 = 203 bytes.
Yeh step kyun? HPACK pehli baar actual bytes transmit karna hi padega — tum kisi cheez ko reference nahin kar sakte jo decoder ne abhi dekha hi nahin. Ab hum name-index byte (jiska 6-bit prefix 01 field-type marker se seedha aata hai) aur (2-byte) value-length prefix include karte hain jo ek naive estimate ignore karta. Ek baar bhejne se dono sides isko apna dynamic-table index (index 62) seekh jaate hain.
HPACK requests 2..100 (indexed): har ek index 62 ko indexed representation se reference karta hai, jiska single top flag bit 1 hai aur 7-bit prefix chhod deta hai. Kyunki 62 < 2 7 − 1 = 127 , yeh single byte hai. Toh 1 byte each, 99 baar:
hpack = 203 + 99 × 1 = 302 bytes .
Yeh step kyun? Table entry exist hone ke baad, poora header ek index byte mein collapse ho jaata hai. Yahi dynamic table ka payoff hai, ab exactly count kiya gaya hai request 1 ke real overhead including.
Savings ratio:
hpack raw = 302 20000 ≈ 66.2 × chhota .
Yeh step kyun? Akele do totals nahin batate ki HPACK kitna matter karta hai — ek ratio batata hai, aur woh ratio is example ka poora learning objective hai: yeh "compression helps" ko concrete "is header ke liye wire par 66× kam bytes" mein badal deta hai. Raw ko HPACK se divide karne se ek dimensionless multiplier milta hai (bytes ÷ bytes), jo compression factor express karne ka standard tarika hai, taaki tum ise gzip claims ya HTTP-1.1 ke zero-compression baseline se compare kar sako.
Answer: raw = 20000 B; HPACK = 302 B (saare overhead including); ratio ≈ 66.2 × .
Verify: 200 × 100 = 20000 ; request 1 = 1 + 2 + 200 = 203 ; total = 203 + 99 = 302 ; 20000/302 = 66.22 …
Yeh step kyun? Hum steps se independently arithmetic dobara karte hain slip pakdne ke liye — aur 2-byte length prefix (200 = 127 + 73 , 73 < 128 ⇒ single continuation byte) re-derive karte hain taaki "203" faith par na ho. Units poore mein bytes hain, dimensionally consistent.
Worked example Ek client 3 requests karta hai; server 2 resources push karta hai. Har Stream ID list karo.
Forecast: parent note ne kaha tha client IDs odd hote hain, server-push IDs even hote hain. Padhne se pehle exact IDs guess karo.
Steps:
Client-initiated streams odd IDs use karte hain, 1 se start karke, badhte hue: request 1 → 1 , request 2 → 3 , request 3 → 5 .
Yeh step kyun? Odd IDs client ke liye reserved hain taaki dono sides kabhi same number na choose karein. Client counts 1 , 3 , 5 , … — evens bilkul skip karo.
Server-pushed streams even IDs use karte hain, 2 se start karke: pehla push → 2 , doosra push → 4 .
Yeh step kyun? Evens server ke hain. Kyunki do sets (odds, evens) disjoint hain, ek client stream aur ek pushed stream kabhi bhi collide nahin kar sakte, chahe woh ek connection share karein.
Stream ID 0 connection-level frames ke liye reserved hai (jaise SETTINGS, WINDOW_UPDATE jo poore connection par apply hote hain, kisi single stream par nahin).
Yeh step kyun? Degenerate ID cover karta hai: 0 na odd-client hai na even-push — yeh "sab ka" channel hai.
Answer: client streams 1, 3, 5; pushed streams 2, 4; connection-level control channel 0.
Verify: odds aur evens disjoint sets hain, toh { 1 , 3 , 5 } ∩ { 2 , 4 } = ∅ ✓ (koi collision nahin). Har ID < 2 31 − 1 hai (31-bit Stream ID field limit): max = 5 ≪ 2 31 − 1 ✓. Saare client IDs odd hain (1 , 3 , 5 ) aur saare push IDs even (2 , 4 ) ✓. Units check: Stream ID ek pure integer label hai, koi dimension nahin — theek hai.
Intuition Figure key (yeh padho chahe image load na ho)
Figure ek horizontal line draw karta hai = ek single TCP connection, bytes left → right flow kar rahe hain, in order . Us line par chhe rounded boxes (frames) hain send order mein: coral boxes stream 1 ke DATA frames hain, mint boxes stream 3 ke DATA frames hain. Teesra box grey hai red "X" ke saath — ek lost TCP segment . Ek coral arrow lost box ke baad se right edge tak span karta hai, labelled "all later bytes (both streams) STALL until retransmit = TCP HOL". Neeche ek chhota do-box legend coral→stream 1, mint→stream 3 map karta hai. Narrative: do streams ke frames freely interleave hote hain (coral, mint, coral, mint), lekin jaise hi ek segment drop hota hai, uske right ka har box — coral aur mint — freeze ho jaata hai jab tak TCP missing bytes redeliver nahin karta.
[!example] Do responses ek connection share karte hain; ek packet lost ho jaata hai. Actually kya block hota hai?
Forecast: HTTP/2 "head-of-line blocking remove karta hai". Toh stream 1 par lost packet stream 3 block nahin karna chahiye... right? Guess karo, phir check karo.
Steps:
Normal case (no loss): frames freely interleave hote hain: DATA(1), DATA(3), DATA(1), DATA(3). Har side Stream ID se sort karta hai. Stream 3 finish ho jaata hai chahe stream 1 bahut bada aur slow ho.
Yeh step kyun? HTTP layer par, streams independent hain — yahi exactly multiplexing ka win hai. Ek slow stream 1 stream 3 ko ab block nahin karta. (Compare karo HTTP-1.1 se, jahan response 1 pehle poora finish hona chahiye.)
Loss case (limiting scenario): figure mein grey red-X box ek TCP segment hai jo drop ho gaya. TCP bytes in order deliver karna chahiye, toh woh baad ke har byte ko hold karta hai — mint stream-3 boxes including — jab tak lost segment retransmit nahin ho jaata.
Yeh step kyun? Yahi trap hai jo parent ne flag kiya tha. HTTP/2 ne application -layer HOL remove kiya lekin transport -layer HOL nahin, kyunki ek TCP connection mein ek ordered byte stream hota hai. In-order delivery kyun force hoti hai yeh TCP mein dekho.
Fix: HTTP-3-and-QUIC UDP par run karta hai aur har stream ko uska apna ordering deta hai, toh ek lost packet sirf apni stream stall karta hai.
Yeh step kyun? Case close karta hai: transport HOL ko truly kill karne ka ek hi tarika hai — transport change karo.
Answer: no loss → full independence; ek lost TCP segment → saari streams stall (TCP HOL); QUIC ise remove karta hai.
Verify: logically, 1 TCP conn par HTTP/2 streams = 1 ordered byte stream, toh ek gap baad ke saare bytes block karta hai. Parent ke [!mistake] callout ke saath consistent. ✓
style.css (5 KiB) push karta hai. Case (i): browser ka koi cache nahin tha. Case (ii): browser ne already cache kar rakha tha. Net bytes?
Forecast: push ek round trip bachata hai. Lekin kya yeh hamesha win hai? Case (ii) ka outcome guess karo.
CSS ko S = 5 KiB = 5 × 1024 = 5120 bytes hone do, aur ek round-trip time cost ko hum RTT kehte hain.
Steps:
Case (i) — cold cache: server 5 KiB push karta hai jo browser ko waise bhi chahiye tha, aur ek RTT bachata hai (koi separate request nahin chahiye). Net data = 5120 bytes (waise bhi fetch hoti), minus latency ka ek round trip.
Yeh step kyun? Yahan push apna kaam karta hai: resource browser ke HTML parser ke maangne se pehle aa jaata hai. Yahi intended win hai.
Case (ii) — warm cache: browser ke paas already style.css hai. Server, yeh na jaante hue, phir bhi saare 5120 bytes push karta hai. Wasted data = 5120 bytes, aur usse bhi bura — woh bytes shared congestion window ke liye compete karte hain us actual HTML ke saath jo browser urgently chahta tha (dekho TCP ).
Yeh step kyun? Yahi real-world footgun hai. Push ke paas koi reliable "kya tumhare paas yeh already hai?" negotiation nahin hai, toh yeh gamble karta hai. Net effect page loads slow kar sakta hai.
Modern replacement: 103 Early Hints + <link rel=preload> browser ko batata hai kya fetch karna hai , browser ko apne decision lene deta hai (apna cache respect karte hue) — koi waste bytes nahin.
Yeh step kyun? Explain karta hai kyun Chrome ne push deprecate kiya: cache-aware pull blind push ko beat karta hai.
Answer: cold cache 1 RTT bachata hai 5120 bytes ke saath achhe se; warm cache 5120 bytes waste karta hai aur hurt kar sakta hai. Push hamesha fast nahin hota.
Verify: case (ii) mein wasted bytes = 5 × 1024 = 5120 > 0 ✓ — ek strict loss, confirm karta hai ki "push hamesha faster" false hai.
Worked example Tumhe ek 5-bit prefix integer field se bytes
31, 128, 1 milte hain. Kaunsa integer I hai yeh?
Forecast: pehle byte ka prefix 31 = 2 5 − 1 hai, overflow marker. Toh aur bytes follow karte hain. I reconstruct karo.
Steps:
First byte prefix = 31 = 2 5 − 1 → yeh "prefix full" marker hai. Running total 31 se shuru karo.
Yeh step kyun? Decoding encoding ka mirror hai: marker dekhne se pata chalta hai continuation bytes padho aur unka contribution 31 ke upar add karo. (Is byte ke 3 high flag bits ignore karo — woh representation type ke hain, integer ke nahin.)
Continuation bytes padho, har ek ( byte mod 128 ) times ek place value 12 8 k contribute karta hai, jahan k continuation bytes 0 se count karta hai. High bit (128) ka matlab "aur follow kar rahe hain":
Byte 128 : high bit set → aur follow kar rahe hain. Value = 128 − 128 = 0 , place 12 8 0 = 1 . Contribution 0 × 1 = 0 .
Byte 1 : high bit set nahin → last byte. Value = 1 , place 12 8 1 = 128 . Contribution 1 × 128 = 128 .
Yeh step kyun? Yeh varint decoding hai: little-endian 7-bit groups. Place value har byte mein 128 se badhta hai kyunki har group 7 bits hold karta hai (2 7 = 128 ).
Sum: I = 31 + 0 + 128 = 159 .
Yeh step kyun? Marker plus reconstructed leftover original integer deta hai.
Answer: I = 159 .
Verify: 159 ko re-encode karo: 2 5 − 1 = 31 , leftover 159 − 31 = 128 . 128 ≥ 128 : emit ( 128 mod 128 ) + 128 = 0 + 128 = 128 , phir ⌊ 128/128 ⌋ = 1 ; 1 < 128 emit 1 . Bytes 31, 128, 1. ✓ Exactly round-trip hota hai.
Yeh step kyun? Encoding aur decoding exact inverses hone chahiye; decoded answer ko re-encode karna aur original bytes se match karna sabse strong sanity check hai.
Recall Self-test — answers cover karo
Structurally "5-bit prefix" kya hota hai? ::: Ek byte ke low 5 bits integer ka (start) hold karte hain; top 3 bits flag bits hain jo representation type se set hote hain.
"Literal with incremental indexing" (01) representation kitne flag bits aur prefix bits use karta hai? ::: Top par 2 flag bits (01), name index ke liye 6-bit prefix.
5-bit prefix ke liye 2 N − 1 kya hai, aur woh value special kyun hai? ::: 31 ; yeh reserved overflow marker hai, toh koi bhi I ≥ 31 (including 31 itself) continuation bytes use karna chahiye.
I = 10 ko 5-bit prefix mein encode karo (poora byte dikhao). ::: Ek byte 000 01010.
I = 31 ko 5-bit prefix mein encode karo. ::: Do bytes: 31, 0.
Bytes 31, 154, 10 decode karo (5-bit prefix). ::: 31 + 26 + 1280 = 1337 .
Kya I negative ho sakta hai? ::: Nahin — HPACK integers sirf non-negative hote hain; koi sign bit nahin hai, aur over-long continuation runs errors ki tarah reject hote hain.
Client kaun se Stream IDs use karta hai, aur server push kaun se? ::: Client = odd (1,3,5,…); server push = even (2,4,…); 0 = connection-level.
Kya HTTP/2 multiplexing TCP-level head-of-line blocking remove karta hai? ::: Nahin — sirf application-layer HOL. Ek lost TCP segment phir bhi saari streams stall karta hai; QUIC ise fix karta hai.
Server push kab hurt karta hai? ::: Jab already-cached resource push karta hai, bytes waste karte hain aur real HTML se congestion-window capacity chheen lete hain.
Mnemonic "Marker means more"
Jab prefix bits saare 1s hote hain (= 2 N − 1 ), number fit nahin hua — aage padho. Continuation bytes: high bit set = aur aa raha hai , high bit clear = ho gaya. Encoding aur decoding dono mein same rule.
See also: Huffman-Coding (HPACK literal strings kaise compress karta hai), Varint-encoding (7-bit continuation trick), CRIME-and-BREACH-attacks (kyun HPACK naive gzip avoid karta hai), TLS aur TCP (handshake aur ordering costs), HTTP-3-and-QUIC (transport-HOL fix).