এই পর্বে যা শিখবেন
- Data link স্তরের সেবাগুলো আর LLC/MAC — দুই উপস্তরের ভাগ
- Character count, byte stuffing আর bit stuffing — হাতে করে encode আর decode
- Stop-and-wait-এ হারানো frame আর হারানো ACK কীভাবে সামলানো হয়, আর efficiency-র সূত্র প্রমাণসহ
- Go-Back-N আর Selective Repeat — ধাপে ধাপে trace, window-এর সর্বোচ্চ আকারের প্রমাণ
- পরীক্ষার ধাঁচের অঙ্ক: efficiency, প্রয়োজনীয় window আর sequence bit-এর সংখ্যা
১ · Data link স্তর — পাশের স্টেশন পর্যন্ত ঠিকঠাক পৌঁছানো
পর্ব ০৭ আর ০৮-এ দেখেছেন, physical layer শুধু bit পাঠায় — তারে ভোল্টেজ, fiber-এ আলো, বাতাসে তরঙ্গ। কোন bit কোন বার্তার অংশ, কোথায় শুরু কোথায় শেষ, পথে কোনো bit উল্টে গেল কি না — এসব নিয়ে physical layer মাথা ঘামায় না। এই দায়িত্ব তার ঠিক ওপরের স্তরের: data link layer.
ঢাকা থেকে রাজশাহীতে একটি পার্সেল যাবে কুরিয়ারে। পুরো যাত্রা কয়েকটি ধাপে: ঢাকার অফিস → সিরাজগঞ্জের হাব → রাজশাহীর অফিস। প্রতিটি ধাপে দুই অফিসের মধ্যে একটি নিজস্ব চুক্তি থাকে: বস্তায় কতগুলো পার্সেল, প্রতিটির গায়ে নম্বর, পৌঁছালে প্রাপ্তিস্বীকার রসিদ, আর একটি বস্তা না পৌঁছালে আবার পাঠানো। Data link স্তর ঠিক এই এক ধাপের চুক্তি — পাশের স্টেশন পর্যন্ত। ঢাকা থেকে রাজশাহী পুরো পথের দায় অন্য স্তরের (network আর transport — পর্ব ১৫, ২৭)।
Data link স্তর সাধারণত এই চারটি সেবা দেয়:
Framing
ওপরের স্তরের packet-কে frame-এ মুড়ে দেওয়া — সামনে header, পেছনে trailer — আর bit-এর স্রোতে প্রতিটি frame-এর সীমানা চেনানো।
অংশ ২Error control
নষ্ট frame ধরা (FCS, পর্ব ০৯) আর দরকার হলে আবার পাঠানো — একে বলে error control.
অংশ ৩–৬Flow control
দ্রুত প্রেরক যেন ধীর প্রাপককে ডুবিয়ে না দেয় — flow control.
অংশ ৩Medium access
অনেকে একই তার বা একই বেতার চ্যানেল ভাগ করলে কে কখন পাঠাবে — পর্ব ১১-এর বিষয়।
পর্ব ১১দুই উপস্তর — LLC আর MAC
LAN-এর মানদণ্ড তৈরি করতে গিয়ে IEEE-র 802 কমিটি data link স্তরকে দুই ভাগ করে। নিচের ভাগ MAC sublayer মাধ্যমের সাথে সরাসরি জড়িত: কে কখন পাঠাবে, frame-এ কোন MAC ঠিকানা বসবে, FCS কীভাবে হবে। এজন্য Ethernet (802.3) আর Wi-Fi (802.11)-এর MAC সম্পূর্ণ আলাদা। ওপরের ভাগ LLC (802.2) মাধ্যম-নিরপেক্ষ: network স্তরকে একই চেহারা দেখায় আর frame-এর ভেতরে কোন protocol-এর ডেটা তা চিহ্নিত করে। বাস্তবে আজকের Ethernet-এ IP বহনের সময় সাধারণত LLC header থাকেই না — frame-এর EtherType ঘর সেই কাজ করে দেয় (পর্ব ১২)। তবে ধারণাটি পরীক্ষায় প্রায়ই আসে।
তিন ধরনের সেবা
| সেবা | কী হয় | কোথায় মানানসই |
|---|---|---|
| ACK ছাড়া, সংযোগ ছাড়া | Frame পাঠিয়ে দেওয়া; নষ্ট হলে প্রাপক চুপচাপ ফেলে দেয় | ত্রুটি খুব কম এমন তারের link — Ethernet |
| ACK-সহ, সংযোগ ছাড়া | প্রতিটি frame-এর প্রাপ্তিস্বীকার; না এলে আবার পাঠানো | ত্রুটি বেশি এমন বেতার link — Wi-Fi |
| ACK-সহ, সংযোগভিত্তিক | আগে সংযোগ স্থাপন, frame-এ নম্বর, ক্রম মেনে ঠিক একবার ডেলিভারি | দীর্ঘ, অনির্ভরযোগ্য link — উপগ্রহ, পুরোনো WAN (HDLC) |
কোনটি বেছে নেওয়া হবে, তা নির্ভর করে link-এ ত্রুটি কত ঘন ঘন হয় তার ওপর। এই প্রশ্নে আমরা অংশ ৮-এ আবার ফিরব। তার আগে প্রথম সমস্যা: frame-এর সীমানা চেনা।
২ · Framing — bit-এর স্রোতে frame-এর শুরু আর শেষ
প্রাপকের কাছে আসে শুধু একটানা bit: 0110100101111110.... এর মধ্যে কোথায় একটি frame শেষ হয়ে পরেরটি শুরু হলো, তা বোঝানোর নিয়মকে বলে framing. চারটি পরিচিত পদ্ধতি আছে।
(ক) Character count — শুরুতে দৈর্ঘ্য লিখে দেওয়া
প্রতিটি frame-এর প্রথম ঘরে লেখা থাকে frame-এ কতগুলো byte. যেমন 5 A B C D মানে এই frame ৫ byte-এর (গোনার ঘরসহ), এরপর পরের frame. সরল, কিন্তু বিপজ্জনক: পথে শুধু গোনার ঘরটি নষ্ট হয়ে 5-এর জায়গায় 7 হলে প্রাপক পরের frame-এর দুটি byte-ও এই frame-এ টেনে নেবে। তারপর ভুল জায়গাকে পরের frame-এর গোনা ভেবে পড়বে, আর এভাবে পুরো স্রোতের সাথে তাল হারাবে। FCS বলতে পারবে frame নষ্ট, কিন্তু পরের frame কোথায় শুরু, তা বলতে পারবে না। এজন্য একা character count প্রায় কোথাও ব্যবহার হয় না; তবে অন্য পদ্ধতির সাথে দৈর্ঘ্যের ঘর রাখা খুবই প্রচলিত।
(খ) Flag byte আর byte stuffing
দ্বিতীয় বুদ্ধি: frame-এর শুরু আর শেষে একটি বিশেষ byte — FLAG. তাল হারালেও প্রাপক শুধু পরের FLAG খুঁজলেই আবার সঠিক জায়গায় ফিরে আসে। কিন্তু নতুন সমস্যা: ছবি বা zip ফাইলের মতো ডেটার ভেতরেও তো FLAG-এর মান থাকতে পারে! তখন প্রাপক সেটিকে frame-এর শেষ ভেবে বসবে।
সমাধান byte stuffing: ডেটার ভেতরে FLAG এলে তার আগে একটি escape byte (ESC) বসানো হয়। আর ডেটায় ESC নিজেই এলে? তার আগেও একটি ESC. প্রাপক নিয়ম জানে: ESC দেখলে সেটি ফেলে দিয়ে পরের byte-টি হুবহু ডেটা হিসেবে নেবে। C-তে স্ট্রিংয়ের ভেতর উদ্ধৃতিচিহ্ন লিখতে \" লেখার কথা ভাবুন — একই বুদ্ধি।
ডেটা: A FLAG B ESC C
পাঠানো frame: FLAG A ESC FLAG B ESC ESC C FLAG
প্রাপক বাঁ থেকে পড়ে: প্রথম FLAG = শুরু; A; ESC দেখে পরের FLAG-কে ডেটা হিসেবে নিল; B; ESC দেখে পরের ESC-কে ডেটা হিসেবে নিল; C; একা FLAG = শেষ। ফল: A FLAG B ESC C — হুবহু।
বাস্তবের PPP (RFC 1662) একটু ভিন্নভাবে করে: FLAG = 0x7E, ESC = 0x7D, আর escape করা byte-কে 0x20 দিয়ে XOR করে পাঠায়। অর্থাৎ 7E হয়ে যায় 7D 5E, আর 7D হয় 7D 5D. ফলে frame-এর ভেতরে কোথাও 7E থাকে না, আর প্রাপক যেকোনো 7E দেখেই নিশ্চিন্তে সীমানা ধরে। খরচ: খুব খারাপ ক্ষেত্রে (সব byte-ই 7E) frame প্রায় দ্বিগুণ লম্বা হয়ে যায়।
(গ) Bit stuffing — HDLC-র কৌশল
Byte stuffing ধরে নেয় ডেটা ৮ bit-এর byte-এ ভাগ করা। কিন্তু যেকোনো দৈর্ঘ্যের bit-স্রোতের জন্য একটি সাধারণ সমাধান আছে — bit stuffing, যা HDLC ব্যবহার করে। Flag হলো 01111110 — অর্থাৎ ছয়টি টানা 1. নিয়ম মাত্র দুটি:
- প্রেরক: ডেটায় টানা পাঁচটি 1 পাঠানোর পর পরের bit যা-ই হোক, একটি 0 বসিয়ে দেয়।
- প্রাপক: টানা পাঁচটি 1-এর পর 0 এলে সেটি মুছে দেয়। পাঁচটি 1-এর পর আবার 1 এলে বোঝে এটি flag (পরের bit 0 হলে) বা ত্রুটি/abort (সাতটি বা বেশি 1).
ফলে ডেটার ভেতরে কখনো ছয়টি টানা 1 যায় না, তাই flag শুধু সীমানাতেই দেখা দেয়। নিচের ডায়াগ্রামে ১৫ bit-এর একটি payload ধাপে ধাপে stuff হচ্ছে — এর ভেতরে flag-এর হুবহু নকশা 01111110-ও আছে।
| বাকি ইনপুট | |
| প্রেরকের আউটপুট | |
| টানা 1-এর গোনা | |
| লাইনে যা যায় | |
| প্রাপকের ফল |
- শুরু। Payload ১৫ bit:
0 11111 1 0 11111 0 1. খেয়াল করুন, শুরুর আটটি bit01111110— হুবহু flag! এভাবে পাঠালে প্রাপক ভাববে frame এখানেই শেষ। - প্রথম পাঁচটি 1. প্রেরক
0আর তারপর পাঁচটি 1 পাঠাল। গোনা ৫ হতেই নিয়ম অনুযায়ী একটি বাড়তি0বসাল — আউটপুট0111110, গোনা আবার শূন্য। ইনপুটের ষষ্ঠ 1-টি এখনো পাঠানো হয়নি, তাই আর ছয়টি টানা 1 হবে না। - পরের দুটি bit.
1(গোনা ১), তারপর0(গোনা শূন্য)। আউটপুট011111010. - আবার পাঁচটি 1. পাঁচটি 1 যাওয়ার পর আবার একটি
0stuff হলো — যদিও ইনপুটের পরের bit এমনিতেই 0. নিয়মে ব্যতিক্রম নেই: পাঁচটি 1-এর পর সবসময় 0 বসে, নইলে প্রাপক বুঝবে না কোন 0 মুছতে হবে। - শেষ দুটি bit আর flag.
0আর1গেল। ১৫ bit হয়ে গেল ১৭ bit; দুই পাশে flag জুড়ে লাইনে গেল মোট ৩৩ bit. ডেটার ভেতরে কোথাও আর111111নেই। - প্রাপক। দুই flag-এর মাঝের ১৭ bit পড়ে, টানা পাঁচটি 1-এর পরের প্রতিটি 0 মুছে দেয় — দুটি 0 মুছে ফিরে এলো
011111101111101, হুবহু আসল payload.
(ঘ) Physical layer-এর coding violation
চতুর্থ পদ্ধতি physical স্তরের সাহায্য নেয়। অনেক line code-এ কিছু সংকেত-নকশা ডেটার জন্য কখনো ব্যবহার হয় না (পর্ব ০৭)। সেই “নিষিদ্ধ” নকশাকে ইচ্ছে করে frame-এর সীমানা হিসেবে পাঠানো যায় — একে বলে coding violation. যেমন 100BASE-TX (Fast Ethernet)-এর 4B/5B কোডে stream-এর শুরু আর শেষ বোঝাতে আলাদা কিছু control symbol আছে, যা কোনো ডেটা-nibble থেকে তৈরি হয় না; পুরোনো Token Ring-এ Manchester কোডের নিয়ম ভাঙা সংকেত দিয়ে সীমানা চিহ্নিত হতো। সুবিধা: stuffing লাগে না, ডেটা বাড়ে না।
বাস্তবের Ethernet কী করে? Ethernet frame-এর আগে ৭ byte-এর preamble (10101010-এর পুনরাবৃত্তি) আর ১ byte-এর start frame delimiter (10101011) থাকে — প্রাপকের ঘড়ি মেলানো আর শুরু চেনার জন্য। শেষটা ঠিক হয় physical স্তরের সংকেত থেকে (সংকেত থেমে যাওয়া বা কোডের নির্দিষ্ট শেষ-চিহ্ন), আর দুই frame-এর মাঝে বাধ্যতামূলক ফাঁক থাকে। তাই Ethernet-এ byte বা bit stuffing নেই। বিস্তারিত পর্ব ১২-এ।
নিচের প্রোগ্রাম দুই ধরনের stuffing-এরই encoder আর decoder — ওপরের stepper-এর payload আর PPP-র নিয়মে একটি byte-উদাহরণ:
// Bit stuffing (HDLC) and byte stuffing (PPP, RFC 1662) - encoder and decoder.
const FLAG = "01111110";
function bitStuff(bits) { // after five 1s in a row, insert a 0
let out = "", ones = 0;
for (const b of bits) {
out += b; ones = b === "1" ? ones + 1 : 0;
if (ones === 5) { out += "0"; ones = 0; }
}
return FLAG + out + FLAG;
}
function bitUnstuff(frame) { // drop the 0 that follows five 1s
const body = frame.slice(8, -8); let out = "", ones = 0, skip = false;
for (const b of body) {
if (skip) { skip = false; ones = 0; continue; } // this is the stuffed 0
out += b; ones = b === "1" ? ones + 1 : 0;
if (ones === 5) skip = true;
}
return out;
}
const hex = a => a.map(x => x.toString(16).toUpperCase().padStart(2, "0")).join(" ");
function byteStuff(data) { // 7E -> 7D 5E, 7D -> 7D 5D
const out = [0x7E];
for (const x of data) x === 0x7E || x === 0x7D ? out.push(0x7D, x ^ 0x20) : out.push(x);
return [...out, 0x7E];
}
function byteUnstuff(f) {
const out = [];
for (let i = 1; i < f.length - 1; i++) out.push(f[i] === 0x7D ? f[++i] ^ 0x20 : f[i]);
return out;
}
const fr = bitStuff("011111101111101");
console.log("bits in : 011111101111101\nframe : " + fr + "\nback : " + bitUnstuff(fr));
const data = [0x41, 0x7E, 0x42, 0x7D, 0x43]; // 'A' FLAG 'B' ESC 'C'
const bf = byteStuff(data);
console.log("bytes in : " + hex(data) + "\nframe : " + hex(bf) + "\nback : " + hex(byteUnstuff(bf)));আউটপুট:
bits in : 011111101111101
frame : 011111100111110101111100101111110
back : 011111101111101
bytes in : 41 7E 42 7D 43
frame : 7E 41 7D 5E 42 7D 5D 43 7E
back : 41 7E 42 7D 43
Bit অংশ: frame-টি ৩৩ bit — প্রথম ৮টি আর শেষ ৮টি flag, মাঝের ১৭ bit হুবহু stepper-এর ধাপ ৫-এর আউটপুট। Decoder দুই flag ছেঁটে প্রতিটি “পাঁচটি 1-এর পরের 0” বাদ দিয়ে আসল ১৫ bit ফেরত দিল। Byte অংশ: ডেটার 7E হয়েছে 7D 5E, 7D হয়েছে 7D 5D (৫ byte-এর ডেটা, দুই flag-সহ ৯ byte-এর frame). ফেরত ডেটা হুবহু মিলেছে। নিজে payload বদলে দেখুন — যেমন টানা দশটি 1 দিলে কতটি 0 stuff হয়।
৩ · Flow control, error control আর ARQ — stop-and-wait
দুটি আলাদা সমস্যা প্রায়ই একসাথে সমাধান করা হয়, তাই গুলিয়ে যায়:
- Flow control — প্রাপকের buffer বা প্রসেসর ধীর হলে প্রেরককে থামানো। এখানে কোনো ত্রুটি নেই, শুধু গতির অমিল।
- Error control — frame নষ্ট বা হারিয়ে গেলে টের পাওয়া আর আবার পাঠানো।
দুটিরই সবচেয়ে প্রচলিত সমাধান ARQ (automatic repeat request) পরিবারের protocol. এর তিনটি উপকরণ:
- ACK — প্রাপকের প্রাপ্তিস্বীকার। ACK না পাঠিয়ে প্রাপক প্রেরককে থামিয়েও রাখতে পারে — এটাই flow control.
- Timer — প্রতিটি frame পাঠিয়ে প্রেরক একটি timer চালু করে। নির্দিষ্ট সময়ে ACK না এলে timeout হয়, আর frame আবার যায়। নষ্ট frame প্রাপক FCS দেখে ফেলে দেয় (পর্ব ০৯), কোনো উত্তর দেয় না — তাই নষ্ট আর হারানো, দুটিই timeout দিয়ে ধরা পড়ে।
- Sequence number — frame-এ ক্রমিক নম্বর, যাতে প্রাপক একই frame দুবার পেলে বুঝতে পারে।
Stop-and-wait: একটি পাঠানো, তারপর ACK-এর অপেক্ষা
সবচেয়ে সরল ARQ হলো stop-and-wait: একটি frame পাঠিয়ে তার ACK না আসা পর্যন্ত প্রেরক আর কিছু পাঠায় না। মুদি দোকানের ছেলেটি একবারে একটি বস্তা ভ্যানে নিয়ে বাড়িতে পৌঁছে দেয়, আর মালিক “পেয়েছি” বললে তবেই পরের বস্তা আনতে যায় — ঠিক এমন।
Sequence number কেন লাগে, দুটি দুর্ঘটনা দিয়ে দেখুন:
প্রেরক প্রাপক
│── F0 (seq 0) ─────────────────────►│ নিল, ওপরে দিল
│◄──────────────────────── ACK 1 ────│ (“এবার 1 চাই”)
│── F1 (seq 1) ───────── ✗ হারাল │
│ ... timer চলছে ... │ কিছুই আসেনি
│ timeout! │
│── F1 (seq 1) আবার ───────────────►│ নিল, ওপরে দিল
│◄──────────────────────── ACK 0 ────│
এখানে নম্বর ছাড়াও কাজ চলত — প্রাপক তো F1 আগে পায়ইনি।
প্রেরক প্রাপক
│── F1 (seq 1) ────────────────────►│ নিল, ওপরে দিল
│ ✗ হারাল ◄──────── ACK 0 ────│
│ timeout! │
│── F1 (seq 1) আবার ───────────────►│ seq 1? আমি তো 0 চাই —
│ │ নকল! ফেলে দিল
│◄──────────────────────── ACK 0 ────│ তবু ACK আবার পাঠাল
│── F2 (seq 0) ────────────────────►│ নিল
নম্বর না থাকলে প্রাপক দ্বিতীয় F1-কে নতুন frame ভেবে ওপরের স্তরে আবার দিত — একই টাকা দুবার জমা হওয়ার মতো ভুল।
Timer খুব ছোট হলে ACK পথে থাকতেই timeout হয়, আর প্রেরক F1 আবার পাঠায়। তখন একটি F1-এর জন্য দুটি ACK আসে। ACK-এও নম্বর থাকলে (ACK 0 মানে “এবার seq 0 চাই”) প্রেরক বুঝতে পারে বাড়তি ACK-টি পুরোনো, পরের frame-এর নয়। তাই frame আর ACK — দুটিতেই নম্বর লাগে, আর timeout-কে অন্তত একটি round trip-এর চেয়ে বড় রাখতে হয়।
Stop-and-wait-এ একসাথে পথে থাকে মাত্র একটি frame, তাই পাশাপাশি দুটি frame-কে আলাদা করতে পারলেই যথেষ্ট: ১ bit-এর নম্বর — 0, 1, 0, 1 … এজন্য একে alternating bit protocol-ও বলে। এখানে ACK-এর নম্বর মানে “পরের যেটি চাই” — অনেক পাঠ্যবইয়ের রীতি; কোনো কোনো বই ACK-এ সদ্য পাওয়া frame-এর নম্বর লেখে। পরীক্ষায় কোন রীতি ধরছেন, তা লিখে দিন।
নিচের C প্রোগ্রাম আসল socket-এ stop-and-wait চালায়। socketpair দুটি জোড়া socket বানায় (OS-এর IPC, অপারেটিং সিস্টেম কোর্সে দেখেছেন), fork করে child হয় প্রাপক, parent প্রেরক। “Lossy” চ্যানেল বানাতে প্রেরক frame 2-এর প্রথম কপি ইচ্ছে করে পাঠায় না, আর প্রাপক frame 3-এর প্রথম ACK ইচ্ছে করে ফেলে দেয়। ACK-এর জন্য অপেক্ষা হয় poll দিয়ে, ২০০ ms timeout-সহ।
#include <stdio.h>
#include <unistd.h>
#include <poll.h>
#include <sys/socket.h>
#include <sys/wait.h>
int main(void) { /* stop-and-wait over a "lossy" socketpair */
int sv[2], sent = 0, lostF = 0;
if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sv) < 0) { perror("socketpair"); return 1; }
fflush(stdout); if (fork() == 0) { /* receiver: prints nothing, only sends ACKs */
char f[2], expect = 0; int accepted = 0, lostA = 0; close(sv[0]);
while (read(sv[1], f, 2) == 2) {
int dup = (f[0] != expect);
if (!dup) { expect ^= 1; accepted++; } /* new frame: deliver it */
char ack = (char)(expect | (dup ? 2 : 0)); /* ACK = next expected seq */
if (accepted == 4 && !lostA) { lostA = 1; continue; } /* ACK of frame 3 lost */
if (write(sv[1], &ack, 1) != 1) break;
}
_exit(0);
}
close(sv[1]); char seq = 0, ack;
for (int i = 0; i < 5; i++, seq ^= 1)
for (;;) {
char f[2] = { seq, (char)('A' + i) };
sent++;
if (i == 2 && !lostF) { lostF = 1; printf("send frame %d seq=%d (lost on the wire)\n", i, seq); }
else { if (write(sv[0], f, 2) != 2) return 1; printf("send frame %d seq=%d\n", i, seq); }
struct pollfd p = { sv[0], POLLIN, 0 };
if (poll(&p, 1, 200) == 0) { printf(" timeout (200 ms) -> resend\n"); continue; }
if (read(sv[0], &ack, 1) != 1) return 1;
printf(" got ACK %d%s\n", ack & 1, (ack & 2) ? " (receiver: duplicate, discarded)" : "");
if ((ack & 1) == (seq ^ 1)) break;
}
close(sv[0]); wait(NULL); printf("5 frames delivered with %d transmissions\n", sent);
return 0;
}আউটপুট:
send frame 0 seq=0
got ACK 1
send frame 1 seq=1
got ACK 0
send frame 2 seq=0 (lost on the wire)
timeout (200 ms) -> resend
send frame 2 seq=0
got ACK 1
send frame 3 seq=1
timeout (200 ms) -> resend
send frame 3 seq=1
got ACK 0 (receiver: duplicate, discarded)
send frame 4 seq=0
got ACK 1
5 frames delivered with 7 transmissions
দুটি দুর্ঘটনাই দেখা গেল। Frame 2 হারানোয় কোনো ACK আসেনি; ২০০ ms পর timeout, তারপর আবার পাঠানো। Frame 3 প্রাপক ঠিকই পেয়েছিল আর ওপরে দিয়েছিল, কিন্তু ACK হারাল; প্রেরক timeout-এর পর আবার পাঠাল। প্রাপক seq 1 দেখে বুঝল এটি নকল (সে চাইছিল 0), তাই ফেলে দিল — কিন্তু ACK আবার পাঠাল, নইলে প্রেরক চিরকাল আটকে থাকত। মোট ৫টি frame পৌঁছাতে ৭ বার পাঠাতে হলো। Socket-এ সত্যিকারের loss হয় না; loss এখানে কোডে বানানো, কিন্তু timeout সত্যিকারের — poll সত্যিই ২০০ ms অপেক্ষা করে।
৪ · Stop-and-wait-এর efficiency — U = 1/(1 + 2a)
Stop-and-wait নির্ভরযোগ্য, কিন্তু কতটা ধীর? পর্ব ০৫-এর দুটি delay (transmission আর propagation) দিয়েই হিসাবটি করা যায়। ধরা যাক:
- Ttrans = L/R — একটি frame-এর সব bit তারে নামাতে সময়;
- Tprop = d/s — একটি bit-এর ওপারে পৌঁছাতে সময়;
- ACK খুব ছোট, তাই তার transmission time আর processing delay নগণ্য; কোনো ত্রুটি নেই।
প্রমাণ: সময় t = 0-তে প্রেরক প্রথম bit পাঠায়। Ttrans-এ শেষ bit তারে নামে, Ttrans + Tprop-এ সেটি প্রাপকের কাছে পৌঁছায়। প্রাপক সঙ্গে সঙ্গে ACK পাঠায়, যা আরও Tprop পরে প্রেরকের কাছে আসে। অর্থাৎ একটি frame-এর পুরো চক্র Ttrans + 2Tprop, যার মধ্যে link কাজের ডেটা বহন করে শুধু Ttrans সময়। তাই
এখানে U (link utilization বা efficiency) হলো মোট সময়ের কত ভাগ link নতুন ডেটা বহন করছে, আর throughput = U × R. সংখ্যা a-র একটি সুন্দর অর্থ আছে: link-এর ওপর একসাথে কতগুলো frame “ধরে” — R × Tprop হলো পথে থাকা bit (পর্ব ০৫-এর bandwidth-delay product-এর একমুখী রূপ), আর তাকে L দিয়ে ভাগ করলে a. a ছোট মানে link “খাটো” (frame তারের চেয়ে লম্বা), a বড় মানে link “লম্বা”।
সমাধান করা অঙ্ক
১,০০০ byte-এর frame, ১ Mbps link, দৈর্ঘ্য ২,০০০ km, s = ২ × ১০৮ m/s.
- L = ৮,০০০ bit; Ttrans = ৮,০০০ ÷ ১০৬ = ৮ ms
- Tprop = ২ × ১০৬ ÷ ২ × ১০৮ = ১০ ms; a = ১০ ÷ ৮ = ১.২৫
- U = ১ ÷ (১ + ২.৫) = ১ ÷ ৩.৫ ≈ ০.২৮৬ (২৮.৬%); throughput ≈ ২৮৫.৭ kbps — ১ Mbps-এর link-এ!
৫০ kbps চ্যানেল, ১,০০০ bit-এর frame, একমুখী propagation ২৫০ ms (মাটি → উপগ্রহ → মাটি)।
- Ttrans = ১,০০০ ÷ ৫০,০০০ = ২০ ms; a = ২৫০ ÷ ২০ = ১২.৫
- U = ১ ÷ (১ + ২৫) = ১ ÷ ২৬ ≈ ৩.৮৫% — ৫২০ ms-এর চক্রে link কাজ করে মাত্র ২০ ms. প্রায় ৯৬% সময় প্রেরক বসে থাকে।
১০ Mbps, ১০০ m তামার তার (s = ২ × ১০৮), ১,০০০ bit-এর frame.
- Ttrans = ১০০ µs; Tprop = ০.৫ µs; a = ০.০০৫
- U = ১ ÷ ১.০১ ≈ ৯৯.০% — ছোট link-এ stop-and-wait-ই যথেষ্ট ভালো।
ত্রুটি থাকলে: U = (1 − p)/(1 + 2a)
এবার ধরুন প্রতিটি frame নষ্ট হওয়ার সম্ভাবনা p (ACK কখনো হারায় না), আর timeout ঠিক এক চক্রের সমান। প্রতিটি চেষ্টা স্বাধীনভাবে সফল হয় (1 − p) সম্ভাবনায়, তাই একটি frame পৌঁছাতে গড়ে কতবার পাঠাতে হয়, তা geometric distribution-এর গড়:
অঙ্ক ১-এ p = ০.০১ হলে U = ০.৯৯ ÷ ৩.৫ ≈ ২৮.৩%. এটি Stallings-এর পাঠ্যবইয়ের মডেল; বাস্তবে timeout এক চক্রের চেয়ে বড় রাখা হয়, ACK-ও হারাতে পারে, তাই আসল efficiency এর চেয়ে কিছুটা কম হয়। বিভিন্ন বই সামান্য আলাদা অনুমান করে (যেমন ACK-এর transmission time ধরা), তাই প্রশ্নে কোন অনুমান দেওয়া আছে তা মিলিয়ে নিন।
প্রচলিত ভুল: (১) a-কে উল্টে Ttrans/Tprop ধরা। (২) সূত্রে ২-এর গুণ বাদ দেওয়া — ACK-কেও ফিরে আসতে হয়, তাই propagation দুবার। (৩) “RTT” দেওয়া থাকলে সেটি নিজেই 2Tprop, আবার ২ দিয়ে গুণ করা নয়। (৪) Byte-কে bit-এ না বদলানো (পর্ব ০৫-এর সেই পুরোনো ফাঁদ)।
৫ · Sliding window আর Go-Back-N
উপগ্রহের উদাহরণে প্রেরক ৯৬% সময় বসে ছিল। সমাধান সহজ: ACK-এর অপেক্ষা না করে একসাথে কয়েকটি frame পাঠিয়ে দেওয়া — একে বলে pipelining (পর্ব ০৪-এর মতোই একসাথে অনেক টুকরো পথে রাখার বুদ্ধি)। কিন্তু সীমাহীন নয়: প্রেরক ACK ছাড়া সর্বোচ্চ W-টি frame পথে রাখতে পারে। এই W-টি নম্বরের জানালাকে বলে sliding window: সবচেয়ে পুরোনো frame-এর ACK এলে জানালা সামনে সরে (slide), আর নতুন একটি frame পাঠানোর অনুমতি মেলে।
একটি কুরিয়ার অফিসের নিয়ম: “প্রাপ্তিস্বীকার না পাওয়া পার্সেল একসাথে সর্বোচ্চ ৪টি রাস্তায় থাকতে পারে।” প্রতিটি পার্সেলে tracking নম্বর। ১ নম্বরের রসিদ এলে ৫ নম্বর রওনা দিতে পারে, ২-এর রসিদ এলে ৬ — জানালাটি নম্বরের সারির ওপর দিয়ে সরে সরে যায়। পার্সেল আর রসিদ রাস্তায় থাকার সময়টুকু আর নষ্ট হয় না।
Sequence number m bit-এর হলে নম্বর চলে 0 থেকে 2m − 1, তারপর আবার 0 (modulo 2m). কোনো frame হারালে কী হবে, তার দুটি নীতি — Go-Back-N আর Selective Repeat.
Go-Back-N-এর নিয়ম
- প্রাপক: window মাত্র ১ — শুধু ঠিক যে নম্বরটি আশা করছে সেটিই নেয়। ক্রমের বাইরের frame (আগেরটি হারানোয় পরে এসে গেছে) ঠিক থাকলেও ফেলে দেয়। প্রাপকের buffer-এর দরকার প্রায় নেই।
- ACK: cumulative ACK — “ACK k” মানে “k-এর আগের সব পেয়েছি, এবার k চাই”। ক্রমের বাইরের frame পেলে প্রাপক শেষ ACK-টিই আবার পাঠায়।
- প্রেরক: সবচেয়ে পুরোনো অস্বীকৃত frame-এর timeout হলে সেটি থেকে শুরু করে পরের সব পাঠানো frame আবার পাঠায় — “N ধাপ পিছিয়ে যাওয়া”।
নিচের Go-Back-N trace-এ W = ৪, ৮টি frame (0–7), আর frame 2-এর প্রথম কপি হারায়। সময়ের একক = একটি frame-এর transmission time; Tprop = ২, তাই t-তে পাঠানো frame পৌঁছায় t + ৩-এ, ACK ফেরে t + ৫-এ; timeout = পাঠানোর ৬ একক পর। (অংশ ৭-এর simulator ঠিক এই সংখ্যাগুলোই দেয়।)
| সময় t | |
| প্রেরকের window | |
| পাঠানো | |
| প্রাপক | |
| প্রেরকে পৌঁছানো ACK | |
| মোট transmission |
- t = ০–৩: window ভরে পাঠানো। প্রেরক 0, 1, 2, 3 পরপর পাঠাল; frame 2 পথে হারাল। চারটি অস্বীকৃত frame, window ভর্তি — এবার ACK-এর অপেক্ষা। t = ৩-এ frame 0 পৌঁছাল, প্রাপক নিল আর ACK1 পাঠাল (“এবার 1 চাই”)।
- t = ৪–৬: জানালা সরছে। ACK1 এলো t = ৫-এ, window সরে [1 2 3 4], তাই 4 গেল। ACK2 এলো t = ৬-এ, window [2 3 4 5], 5 গেল। কিন্তু প্রাপকের কাছে t = ৬-এ এলো frame 3 — সে চাইছে 2, তাই 3 ঠিক থাকলেও ফেলে দিল আর ACK2 আবার পাঠাল।
- t = ৭–৮: timeout. t = ৭-এ window ভর্তি, প্রেরক বসে আছে। t = ৮-এ frame 4 এসে ফেলে দেওয়া হলো, আর একটি নকল ACK2 এলো (window সরে না)। Frame 2 পাঠানো হয়েছিল t = ২-এ, তাই t = ৮-এ তার timer ফুরাল — Go-Back-N পিছিয়ে যায় frame 2-এ।
- t = ৮–১১: সব আবার। প্রেরক 2, 3, 4, 5 আবার পাঠাল — যদিও 3, 4, 5-এর প্রথম কপি ঠিকঠাকই পৌঁছেছিল, শুধু প্রাপক রাখেনি। পুরোনো 5 পৌঁছাল t = ৯-এ, সেটিও ফেলে দেওয়া হলো। নতুন 2 পৌঁছাল t = ১১-এ — এবার প্রাপক নিল, ACK3 পাঠাল।
- t = ১২–১৪: ক্রম ফিরে এলো। আবার পাঠানো 3, 4, 5 পরপর পৌঁছাল আর গৃহীত হলো। ACK3 (t = ১৩) আর ACK4 (t = ১৪) আসতেই 6 আর 7 রওনা দিল।
- t = ১৫–১৯: শেষ। ACK5, ACK6 এলো; 6 আর 7 পৌঁছাল t = ১৬ আর ১৭-এ; ACK8 এলো t = ১৯-এ। ৮টি frame পৌঁছাতে মোট ১২ বার পাঠাতে হলো — ৪টি বাড়তি (হারানো 2 আর অকারণে ফেলে দেওয়া 3, 4, 5).
কেন GBN-এ window ≤ 2m − 1
ধরুন m = ২, নম্বর 0, 1, 2, 3, আর কেউ W = ৪ নিল। প্রেরক 0, 1, 2, 3 পাঠাল; প্রাপক চারটিই পেল, এখন আশা করছে পরের চক্রের 0. দুটি সম্ভাব্য ঘটনা:
- ঘটনা A: চারটি ACK-ই হারাল। প্রেরকের timeout, পুরোনো 0 আবার এলো।
- ঘটনা B: সব ACK পৌঁছেছে, প্রেরক নতুন চক্রের 0 পাঠাল।
দুই ক্ষেত্রেই প্রাপক দেখছে “seq 0” আর সে 0-ই চাইছে — পুরোনো আর নতুনকে আলাদা করার কোনো উপায় নেই। ঘটনা A-তে সে পুরোনো ডেটা নতুন ভেবে নেবে। W = ৩ হলে: প্রেরক 0, 1, 2 পাঠায়, প্রাপক আশা করে 3. ঘটনা A-তে পুরোনো 0 আসে (প্রাপক চায় 3 — বাতিল); ঘটনা B-তে নতুন 3 আসে। নম্বর আলাদা, তাই বিভ্রান্তি নেই। সাধারণভাবে: প্রাপক পরের যে নম্বর আশা করছে, তা প্রেরকের window-এর কোনো নম্বরের সাথে মিলে যাওয়া চলবে না। W-টি নম্বর আর পরের একটি — মোট W + 1টি আলাদা নম্বর লাগে, তাই W + 1 ≤ 2m, অর্থাৎ W ≤ 2m − 1.
৬ · Selective Repeat — শুধু যা হারিয়েছে
Go-Back-N-এর অপচয় চোখে পড়ার মতো: ঠিকঠাক পৌঁছানো 3, 4, 5 আবার পাঠাতে হলো। Link-এ ত্রুটি বেশি হলে বা window বড় হলে এই অপচয় অনেক বড়। Selective Repeat (SR) এর সমাধান:
- প্রাপক: নিজেরও W আকারের window রাখে। Window-এর ভেতরের যেকোনো ঠিক frame — ক্রমের বাইরে হলেও — buffer-এ রেখে দেয়। ফাঁক পূরণ হলে একসাথে ক্রম মেনে ওপরে দেয়।
- ACK: প্রতিটি frame-এর আলাদা ACK (ACK k = “frame k পেয়েছি”)। অনেক নকশায় প্রাপক ফাঁক দেখলে NAK পাঠিয়ে timeout-এর আগেই হারানো frame চেয়ে নেয়।
- প্রেরক: প্রতিটি frame-এর আলাদা timer; timeout হলে শুধু সেই frame আবার যায়।
একই পরিস্থিতি (W = ৪, frame 2 হারাল, NAK ছাড়া) এবার SR-এ:
| সময় t | |
| প্রেরকের window | |
| পাঠানো | |
| প্রাপক | |
| প্রাপকের buffer | |
| প্রেরকে পৌঁছানো ACK | |
| মোট transmission |
- t = ০–৩: একই শুরু। 0, 1, 2, 3 গেল, 2 হারাল। Frame 0 পৌঁছাল t = ৩-এ; প্রাপক পাঠাল ACK0 — এখানে ACK-এর নম্বর মানে “এই frame-টি পেয়েছি”।
- t = ৪–৬: পার্থক্য শুরু। ACK0 আর ACK1 এলে window সরে [2 3 4 5], 4 আর 5 গেল। Frame 3 এলো t = ৬-এ — প্রাপক এবার ফেলে দিল না, buffer-এ রেখে ACK3 পাঠাল।
- t = ৭–৮: শুধু 2 আবার। Frame 4-ও buffer-এ গেল। ACK3 এলো, প্রেরক 3-কে “পৌঁছেছে” চিহ্নিত করল, কিন্তু window সরে না — সবচেয়ে পুরোনো 2 এখনো বাকি। t = ৮-এ 2-এর timeout, আর প্রেরক শুধু 2 আবার পাঠাল।
- t = ৯–১২: buffer ভরে খালি। 5-ও buffer-এ গেল। নতুন 2 পৌঁছাল t = ১১-এ — ফাঁক পূরণ! প্রাপক 2, 3, 4, 5 একসাথে ক্রম মেনে ওপরে দিল। প্রেরক এই চার একক বসে থাকল: window [2 3 4 5] ভর্তি, 2-এর ACK না এলে নতুন 6 পাঠানো যায় না।
- t = ১৩–১৪: window লাফ দিল। ACK2 এলো t = ১৩-এ। 3, 4, 5 আগেই স্বীকৃত, তাই window একবারে ৪ ঘর সরে 6-এ। 6 আর 7 রওনা দিল।
- t = ১৫–১৯: শেষ। ACK7 এলো t = ১৯-এ। মোট ৯ বার পাঠানো — হারানো frame-টির জন্য একটিমাত্র বাড়তি। শেষ হওয়ার সময় GBN-এর সমান (t = ১৯), কারণ এখানে window ছোট (৪ < 1 + 2a = ৫) — GBN যে সময়ে বাড়তি frame পাঠাচ্ছিল, SR সেই সময়টা বসে কাটিয়েছে। অপচয় বাঁচল link-এর ক্ষমতায়, সময়ে নয়।
কেন SR-এ window ≤ 2m−1 — বিভ্রান্তির প্রমাণ
SR-এর প্রাপক একটি পুরো window গ্রহণ করে, তাই শর্তটি আরও কঠিন। আবার m = ২ (নম্বর 0–3), আর ধরুন W = ৩:
- প্রেরক 0, 1, 2 পাঠাল। প্রাপক তিনটিই পেল, ACK দিল, আর তার window সরে গেল {3, 0, 1}-এ (পরের চক্রের নম্বর)।
- তিনটি ACK-ই হারাল। প্রেরকের timeout — সে পুরোনো frame 0 আবার পাঠাল।
- প্রাপকের window-এ 0 আছে! সে পুরোনো 0-কে পরের চক্রের নতুন 0 ভেবে গ্রহণ করল — ভুল ডেটা ওপরে যাবে।
W = ২ হলে: প্রেরক 0, 1; প্রাপকের নতুন window {2, 3}. পুরোনো 0 বা 1 আবার এলে তা window-এর বাইরে — প্রাপক চেনে এটি নকল, ফেলে দিয়ে ACK আবার পাঠায়। সাধারণ প্রমাণ: প্রাপক W-টি frame পেয়ে window সরালে তার নতুন window হয় [W, 2W − 1] (mod 2m). প্রেরক তখনো পুরোনো [0, W − 1]-এর যেকোনোটি আবার পাঠাতে পারে। দুটি window-এর মোট 2W-টি নম্বর আলাদা না হলে বিভ্রান্তি — তাই 2W ≤ 2m, অর্থাৎ W ≤ 2m−1.
| বৈশিষ্ট্য | Stop-and-wait | Go-Back-N | Selective Repeat |
|---|---|---|---|
| প্রেরকের window | ১ | ≤ 2m − 1 | ≤ 2m−1 |
| প্রাপকের window | ১ | ১ | প্রেরকের সমান |
| ACK | প্রতি frame | Cumulative | প্রতি frame আলাদা (NAK-ও থাকতে পারে) |
| Loss হলে আবার যায় | সেই frame | সেটি থেকে পরের সব | শুধু সেই frame |
| প্রাপকের buffer | নগণ্য | নগণ্য | W-টি frame |
| জটিলতা | সবচেয়ে সরল | মাঝারি | সবচেয়ে বেশি |
| m = ৩ হলে সর্বোচ্চ W | ১ | ৭ | ৪ |
৭ · Sliding window-এর efficiency আর পরীক্ষার অঙ্ক
প্রমাণ: t = 0-তে প্রেরক টানা পাঠানো শুরু করে। প্রথম frame-এর ACK ফেরে Ttrans + 2Tprop = (1 + 2a)Ttrans সময়ে। এই সময়ের মধ্যে প্রেরক window-এর W-টি frame পাঠাতে পারে, যাতে লাগে W·Ttrans.
- W ≥ 1 + 2a হলে প্রথম ACK আসার আগেই window ফুরায় না — ACK আসতেই থাকে, প্রেরক কখনো থামে না: U = 1.
- W < 1 + 2a হলে প্রতি (1 + 2a)Ttrans চক্রে মাত্র W·Ttrans সময় কাজ, বাকিটা অপেক্ষা: U = W/(1 + 2a).
ত্রুটি থাকলে (frame নষ্টের সম্ভাবনা p) Stallings-এর পাঠ্যবইয়ের মডেলে সূত্রগুলো এমন (ACK হারায় না ধরে, আর বই-ভেদে অনুমান সামান্য আলাদা হতে পারে):
| Protocol | W ≥ 1 + 2a | W < 1 + 2a |
|---|---|---|
| Stop-and-wait | U = (1 − p)/(1 + 2a) | |
| Selective Repeat | U = 1 − p | U = W(1 − p)/(1 + 2a) |
| Go-Back-N | U = (1 − p)/(1 + 2ap) | U = W(1 − p)/((1 + 2a)(1 − p + Wp)) |
SR-এর সূত্র সহজবোধ্য: প্রতিটি নষ্ট frame-এর জন্য শুধু একটি বাড়তি পাঠানো, তাই গড়ে ১/(১ − p) বার। GBN-এর হরে 2ap এসেছে কারণ প্রতিটি ত্রুটিতে প্রায় পুরো একটি round trip-এর frame (প্রায় 1 + 2a-টি) আবার পাঠাতে হয়। নিচের calculator সূত্রগুলো দিয়ে একটি টেবিল বানায়:
// Link utilization U (fraction of time the sender's link carries new, useful frames).
// a = Tprop / Ttrans, P = probability a frame is damaged (ACKs never lost) - Stallings' model.
const sw = (a, P) => (1 - P) / (1 + 2 * a);
const sr = (W, a, P) => W >= 2 * a + 1 ? 1 - P : W * (1 - P) / (2 * a + 1);
const gbn = (W, a, P) => W >= 2 * a + 1 ? (1 - P) / (1 + 2 * a * P)
: W * (1 - P) / ((2 * a + 1) * (1 - P + W * P));
const pct = u => ((100 * u).toFixed(1) + "%").padStart(8);
console.log("Error-free (P = 0):");
console.log(" a 1+2a | S&W W=7 W=127");
for (const a of [0.005, 0.1, 1.25, 12.5, 100])
console.log(String(a).padStart(7) + String(1 + 2 * a).padStart(6) + " |" +
pct(sw(a, 0)) + pct(sr(7, a, 0)) + pct(sr(127, a, 0)));
console.log("\nWith errors, P = 0.01 (1 frame in 100 damaged):");
console.log(" a | S&W GBN W=7 SR W=7 GBN W=127 SR W=127");
for (const a of [0.005, 1.25, 12.5, 100])
console.log(String(a).padStart(7) + " |" + pct(sw(a, 0.01)) + pct(gbn(7, a, 0.01)) +
pct(sr(7, a, 0.01)) + pct(gbn(127, a, 0.01)) + pct(sr(127, a, 0.01)));
// Example: 1000-byte frames, 1 Mbps, 2000 km of fiber (2e8 m/s)
const Tt = 8000 / 1e6, Tp = 2000e3 / 2e8, a = Tp / Tt;
console.log("\nTtrans=" + Tt * 1e3 + " ms Tprop=" + Tp * 1e3 + " ms a=" + a +
" S&W U=" + pct(sw(a, 0)).trim() + " throughput=" + (sw(a, 0) * 1e3).toFixed(1) + " kbps");আউটপুট:
Error-free (P = 0):
a 1+2a | S&W W=7 W=127
0.005 1.01 | 99.0% 100.0% 100.0%
0.1 1.2 | 83.3% 100.0% 100.0%
1.25 3.5 | 28.6% 100.0% 100.0%
12.5 26 | 3.8% 26.9% 100.0%
100 201 | 0.5% 3.5% 63.2%
With errors, P = 0.01 (1 frame in 100 damaged):
a | S&W GBN W=7 SR W=7 GBN W=127 SR W=127
0.005 | 98.0% 99.0% 99.0% 99.0% 99.0%
1.25 | 28.3% 96.6% 99.0% 96.6% 99.0%
12.5 | 3.8% 25.1% 26.7% 79.2% 99.0%
100 | 0.5% 3.3% 3.4% 27.7% 62.6%
Ttrans=8 ms Tprop=10 ms a=1.25 S&W U=28.6% throughput=285.7 kbps
প্রথম টেবিল: a ছোট (LAN) হলে সবাই প্রায় ১০০%. a = ১২.৫ (উপগ্রহ)-তে stop-and-wait ৩.৮%, W = ৭ নিয়ে ৭/২৬ = ২৬.৯%, আর W = ১২৭ (≥ ২৬) হলে পূর্ণ ১০০%. a = ১০০-তে ১২৭-ও যথেষ্ট নয় — ১২৭/২০১ = ৬৩.২%. দ্বিতীয় টেবিল: ১% ত্রুটিতে পার্থক্য খোলে লম্বা link আর বড় window-এ: a = ১২.৫, W = ১২৭-এ SR ৯৯.০% রাখে, কিন্তু GBN নামে ৭৯.২%-এ — প্রতিটি ত্রুটিতে প্রায় ২৬টি frame আবার পাঠাতে হয়। ছোট window-এ (W = ৭) দুটি প্রায় সমান (২৫.১% বনাম ২৬.৭%), কারণ তখন GBN-এর আবার পাঠানোও সীমিত। শেষ লাইন অংশ ৪-এর অঙ্ক ১ যাচাই করে।
পরীক্ষার ধাঁচের অঙ্ক — window আর sequence bit
অঙ্ক ২-এর উপগ্রহ (a = ১২.৫)। পুরো ব্যবহারের জন্য W ≥ 1 + 2a = ২৬.
- Go-Back-N: 2m − 1 ≥ ২৬ ⇒ 2m ≥ ২৭ ⇒ m = ৫ (৩১ ≥ ২৬)।
- Selective Repeat: 2m−1 ≥ ২৬ ⇒ m − ১ = ৫ ⇒ m = ৬ (৩২ ≥ ২৬)।
- ৩ bit-এর নম্বর নিয়ে GBN-এর W = ৭: U = ৭/২৬ ≈ ২৬.৯%; প্রায় ৭ গুণ ভালো stop-and-wait-এর চেয়ে, তবু পূর্ণ নয়।
এজন্যই HDLC-তে ৩ bit-এর সাধারণ নম্বরের পাশাপাশি ৭ bit-এর “extended” নম্বর (window ১২৭ পর্যন্ত) রাখা হয়েছিল — লম্বা উপগ্রহ link-এর জন্য।
Simulator — একই loss, তিন protocol
নিচের simulator অংশ ৫ আর ৬-এর সময়-হিসাব হুবহু চালায় (Tprop = ২ একক, timeout = ৬, ৮টি frame, ACK কখনো হারায় না), দুটি loss-এর নকশায়:
// Stop-and-wait vs Go-Back-N vs Selective Repeat on the same loss pattern. Time unit = one
// frame's transmission time. Tprop = 2: a frame sent at t arrives at t+3, its ACK is back at t+5.
const N = 8, P = 2, TO = 6; // frames, Tprop, timeout
function run(name, W, sr, lost) {
const sentAt = [], acked = [], got = [], lossLeft = new Set(lost);
let base = 0, next = 0, expect = 0, tx = 0, end = 0, log = [], ev = [], redo = [];
for (let t = 0; base < N; t++) {
for (const e of ev.filter(e => e.t === t)) {
if (e.f !== undefined) { // a frame reaches the receiver
if (sr || e.f === expect) got[e.f] = true; // GBN keeps only the expected one
while (got[expect]) expect++;
ev.push({ t: t + P, a: sr ? e.f : expect }); // SR: ACK this frame; GBN: next expected
} else if (sr) acked[e.a] = true;
else for (let k = base; k < e.a; k++) acked[k] = true;
}
while (acked[base]) base++;
if (base === N) { end = t; break; }
for (let k = base; k < next; k++) // timeouts
if (!acked[k] && sentAt[k] + TO === t) {
log.push("t=" + t + " timeout " + k);
if (sr) redo.push(k); else { next = k; break; }
}
const f = redo.length ? redo.shift() : (next < base + W && next < N ? next++ : -1);
if (f < 0) continue; sentAt[f] = t; tx++;
if (lossLeft.delete(f)) log.push("t=" + t + " send " + f + " LOST");
else ev.push({ t: t + 1 + P, f });
}
console.log(name.padEnd(16) + "transmissions=" + tx + " done at t=" + end + " | " + log.join(", "));
}
for (const lost of [[2], [2, 6]]) {
console.log("Lost first copy of frame(s): " + lost.join(", "));
run("Stop-and-wait", 1, false, lost);
run("Go-Back-N W=4", 4, false, lost);
run("Sel. Repeat W=4", 4, true, lost);
}আউটপুট:
Lost first copy of frame(s): 2
Stop-and-wait transmissions=9 done at t=46 | t=10 send 2 LOST, t=16 timeout 2
Go-Back-N W=4 transmissions=12 done at t=19 | t=2 send 2 LOST, t=8 timeout 2
Sel. Repeat W=4 transmissions=9 done at t=19 | t=2 send 2 LOST, t=8 timeout 2
Lost first copy of frame(s): 2, 6
Stop-and-wait transmissions=10 done at t=52 | t=10 send 2 LOST, t=16 timeout 2, t=36 send 6 LOST, t=42 timeout 6
Go-Back-N W=4 transmissions=14 done at t=25 | t=2 send 2 LOST, t=8 timeout 2, t=13 send 6 LOST, t=19 timeout 6
Sel. Repeat W=4 transmissions=10 done at t=24 | t=2 send 2 LOST, t=8 timeout 2, t=13 send 6 LOST, t=19 timeout 6
কীভাবে কাজ করে: প্রতিটি সময়-এককে (১) ওই মুহূর্তে পৌঁছানো frame আর ACK প্রক্রিয়া হয়, (২) window-এর বাঁ প্রান্ত base সামনে সরে, (৩) timeout দেখা হয় — GBN-এ next = k মানে “k-তে পিছিয়ে যাওয়া”, SR-এ শুধু k-কে আবার পাঠানোর তালিকায় রাখা, (৪) link খালি থাকলে একটি frame পাঠানো হয়। Stop-and-wait হলো W = ১-এর GBN.
ফল পড়া: প্রথম নকশার GBN (১২ বার, t = ১৯) আর SR (৯ বার, t = ১৯) হুবহু দুই stepper-এর সংখ্যা। Stop-and-wait-এ প্রতি frame-এ ৫ একক লাগে, তাই ৮ × ৫ = ৪০, সাথে হারানো চেষ্টার ৬ একক — t = ৪৬. দ্বিতীয় নকশায় দুটি loss: GBN-এর বাড়তি পাঠানো বেড়ে ৬টি (১৪ বার), আর এবার SR সময়েও এক একক এগিয়ে (t = ২৪ বনাম ২৫)। lost তালিকা বা W বদলে নিজে পরীক্ষা করুন — যেমন [5] দিলে কী হয়, অনুশীলন ৩-এ আছে।
Piggybacking — ACK-কে ডেটার পিঠে চড়ানো
এতক্ষণ ডেটা চলেছে এক দিকে। বাস্তবে দুই দিকেই চলে (full-duplex). তখন প্রাপক আলাদা ছোট ACK frame না পাঠিয়ে তার নিজের ডেটা frame-এর header-এ একটি “ack” ঘর রেখে দেয় — একে বলে piggybacking. ঢাকা–রাজশাহী রুটের বাস ফেরার পথে খালি না গিয়ে ফিরতি মাল নিয়ে যায়, আর সাথে আগের চালানের রসিদও। লাভ: আলাদা ACK frame-এর header, FCS আর frame-এর মাঝের ফাঁক বাঁচে। ঝুঁকি: ফিরতি ডেটা না থাকলে ACK আটকে থাকবে — তাই একটি ছোট timer রাখা হয়; সময়মতো ডেটা না এলে আলাদা ACK চলে যায়। HDLC-র I-frame-এ পাঠানো আর গ্রহণ — দুটি নম্বরই থাকে, আর TCP-র প্রতিটি segment-এ ACK ঘর থাকে — দুটোই piggybacking-এর উদাহরণ।
৮ · বাস্তবের protocol — HDLC, PPP, Ethernet আর Wi-Fi
HDLC — পাঠ্যবইয়ের ধারণার বাস্তব রূপ
HDLC-র frame দেখতে এমন (ঘরের মাপ bit-এ; ঠিকানা আর control ঘর বাড়ানো যায়):
┌──────────┬─────────┬─────────┬──────────────────┬──────────┬──────────┐
│ Flag │ Address │ Control │ Information │ FCS │ Flag │
│ 01111110 │ 8 │ 8 / 16 │ variable │ 16 / 32 │ 01111110 │
└──────────┴─────────┴─────────┴──────────────────┴──────────┴──────────┘
- তিন ধরনের frame: I-frame (ডেটা, ভেতরে N(S) = নিজের নম্বর আর N(R) = piggyback করা ACK), S-frame (supervisory — RR “পাঠাতে থাকুন”, RNR “থামুন” অর্থাৎ flow control, REJ = Go-Back-N ধাঁচের আবার পাঠানোর অনুরোধ, SREJ = Selective Repeat ধাঁচের), আর U-frame (unnumbered — সংযোগ স্থাপন, বিচ্ছিন্ন করা ইত্যাদি)।
- নম্বর: সাধারণত ৩ bit (modulo ৮), extended রূপে ৭ bit (modulo ১২৮)।
- তিন mode: NRM (normal response — primary স্টেশন অনুমতি দিলে তবেই secondary পাঠায়, পুরোনো mainframe-terminal লাইনের মতো), ARM (asynchronous response — secondary নিজে থেকে পাঠাতে পারে, কিন্তু নিয়ন্ত্রণ primary-র; খুব কম ব্যবহৃত), আর ABM (asynchronous balanced — দুই প্রান্ত সমান, যে কেউ যেকোনো সময় পাঠায়; point-to-point link-এ সবচেয়ে প্রচলিত)।
PPP আর PPPoE
PPP (RFC 1661) দুই যন্ত্রের সরাসরি link-এর জন্য — একসময় dial-up modem, এখনো কিছু WAN link. এর framing HDLC-ধাঁচের (flag 0x7E, অংশ ২-এর byte stuffing), কিন্তু সাধারণ ব্যবহারে এটি numbered ARQ চালায় না: নষ্ট frame ফেলে দেয়, আবার পাঠানোর দায় ওপরের TCP-র। PPP-র আসল শক্তি অন্যখানে — LCP দিয়ে link-এর শর্ত ঠিক করা, PAP/CHAP দিয়ে ব্যবহারকারী যাচাই, আর NCP (যেমন IPCP) দিয়ে IP ঠিকানা দেওয়া।
এই সুবিধাগুলোর জন্যই PPPoE (RFC 2516) এসেছে: Ethernet-এর ওপর PPP session. বাংলাদেশসহ বহু দেশের অনেক broadband ISP বাড়ির router-এ PPPoE-র username আর password বসিয়ে সংযোগ দেয় — router-এর সেটিংসে “WAN type: PPPoE” দেখে থাকতে পারেন (সব ISP এভাবে করে না; কেউ সরাসরি DHCP বা static IP দেয়)। PPPoE-তে framing-এর কাজ Ethernet করে, তাই byte stuffing লাগে না; তবে PPPoE-র ৮ byte header-এর জন্য IP-র MTU সাধারণত ১,৪৯২ byte-এ নেমে আসে।
Ethernet আবার পাঠায় না — কেন?
তারের Ethernet ACK-ছাড়া সেবা দেয়: FCS না মিললে frame চুপচাপ ফেলে দেয়, প্রেরক জানতেও পারে না। কারণ দুটি। প্রথমত আধুনিক তামার তার আর fiber-এ bit-ত্রুটি অত্যন্ত বিরল — প্রতিটি frame-এ ACK, timer আর buffer-এর খরচ সেই বিরল ত্রুটির তুলনায় অনেক বেশি। দ্বিতীয়ত ওপরে TCP পুরো পথের জন্য নিজেই নির্ভরযোগ্যতা দেয় (পর্ব ৩০)। Link-এ আবার পাঠালে সেই কাজটি দুবার হতো। (পুরোনো half-duplex Ethernet সংঘর্ষ হলে frame আবার পাঠাত — কিন্তু সেটি সংঘর্ষ শনাক্ত করে, ACK দিয়ে নয়; পর্ব ১১।)
Wi-Fi আবার পাঠায় — কেন?
বেতার চ্যানেলে চিত্র উল্টো: দেয়াল, দূরত্ব, মাইক্রোওয়েভ ওভেন, পাশের ফ্ল্যাটের router — ত্রুটি আর সংঘর্ষ খুব সাধারণ। 802.11-এ প্রতিটি unicast ডেটা frame পৌঁছালে প্রাপক খুব ছোট একটি বিরতির (SIFS) পর ACK পাঠায়; ACK না এলে প্রেরক নির্দিষ্ট সীমা পর্যন্ত কয়েকবার আবার চেষ্টা করে — মূলত stop-and-wait. আধুনিক 802.11n/ac/ax-এ অনেক frame একসাথে জুড়ে পাঠিয়ে একটি “block ACK” দিয়ে কোনগুলো পৌঁছেছে জানানো হয় — selective repeat-এর ধাঁচ। কেন TCP-র ওপর ছেড়ে দেওয়া হয় না? কারণ TCP-র timeout অনেক লম্বা (পুরো পথের RTT), আর TCP প্রতিটি loss-কে নেটওয়ার্কের ভিড় ভেবে গতি কমিয়ে দেয় (পর্ব ৩২)। এক hop-এ মিলিসেকেন্ডের কম সময়ে আবার পাঠিয়ে Wi-Fi সেই ভুল সংকেত এড়ায় (পর্ব ১৪)।
আরও গভীরে: TCP আসলে GBN আর SR-এর মিশ্রণ: ACK cumulative (GBN-এর মতো), কিন্তু প্রাপক ক্রমের বাইরের ডেটা রেখে দেয়, আর SACK option (RFC 2018) দিয়ে কোন টুকরোগুলো পেয়েছে জানায় — প্রেরক শুধু ফাঁকগুলো পাঠায় (SR-এর মতো)। TCP-র sequence number ৩২ bit আর byte-ভিত্তিক; খুব দ্রুত link-এ কয়েক সেকেন্ডেই নম্বর ঘুরে আসতে পারে, তাই অংশ ৬-এর “পুরোনো আর নতুন একই নম্বর” সমস্যা ঠেকাতে timestamp-ভিত্তিক PAWS কৌশল (RFC 7323) আছে। বিস্তারিত পর্ব ৩০ আর ৩১-এ।
পরীক্ষা ও ইন্টারভিউতে এই বিষয়ে প্রায়ই যা জিজ্ঞেস করা হয়:
- Stop-and-wait-এর efficiency সূত্র প্রমাণ করুন। — চক্র = Ttrans + 2Tprop, কাজ = Ttrans; তাই U = 1/(1 + 2a), a = Tprop/Ttrans.
- m bit নম্বরে GBN আর SR-এর সর্বোচ্চ window? — GBN: 2m − 1; SR: 2m−1. কারণ প্রেরক আর প্রাপকের window-এর নম্বর মিলে গেলে পুরোনো নকল নতুন বলে গৃহীত হয়।
0111111110-এ bit stuffing করলে কী হয়? — প্রথম পাঁচটি 1-এর পর একটি 0 বসে, বাকি অংশ অপরিবর্তিত:01111101110.- Flow control আর error control-এর পার্থক্য? — প্রথমটি গতির অমিল সামলায় (প্রাপককে ডুবতে না দেওয়া), দ্বিতীয়টি নষ্ট/হারানো frame সামলায় (ধরা আর আবার পাঠানো)।
- Ethernet-এ ARQ নেই, Wi-Fi-তে আছে কেন? — তারে ত্রুটি বিরল আর TCP পুরো পথ সামলায়; বেতারে ত্রুটি বেশি, আর TCP loss-কে ভিড় ভেবে গতি কমায়, তাই এক hop-এই দ্রুত আবার পাঠানো লাভজনক।
৯ · AI-এর যুগে ARQ-এর অঙ্ক আর protocol-এর তথ্য
“Stop-and-wait efficiency, 2 km, 10 Mbps…” AI-কে দিলে চকচকে সমাধান আসবে। কিন্তু এই বিষয়ের অঙ্কে AI-এর ভুলগুলোর ধরন চেনা — বেশিরভাগই সূত্রের রীতি আর অনুমানে, যা আত্মবিশ্বাসী ভাষায় ঢাকা পড়ে।
| AI-এর ভুল | কেন ভুল | কীভাবে ধরবেন |
|---|---|---|
| SR-এর সর্বোচ্চ window 2m − 1 বলা | এটি GBN-এর সীমা; SR-এ 2m−1 | অংশ ৬-এর m = ২ উদাহরণটি হাতে চালান |
| U = 1/(1 + a) লেখা বা RTT-কে আবার দ্বিগুণ করা | ACK-কেও ফিরতে হয়; RTT নিজেই 2Tprop | সময়রেখা এঁকে চক্রটি গুনুন |
| Bit stuffing-এ ছয়টি 1-এর পর 0 বসানো | নিয়ম পাঁচটি 1-এর পর | অংশ ২-এর encoder-এ চালিয়ে মেলান |
| “Ethernet ACK দিয়ে নির্ভরযোগ্যতা দেয়” | তারের Ethernet ACK-ছাড়া; Wi-Fi ACK দেয় | IEEE 802.3 বনাম 802.11-এর বর্ণনা মেলান |
| ACK-এর নম্বরের রীতি মিশিয়ে ফেলা | কোনো বইয়ে “পরের চাই”, কোনোটায় “এটি পেয়েছি” | উত্তরে কোন রীতি তা স্পষ্ট লিখতে বলুন |
| বানানো RFC নম্বর (যেমন PPPoE বা SACK-এর ভুল নম্বর) | ভাষার মডেল বিশ্বাসযোগ্য নম্বর বানাতে পারে | rfc-editor.org-এ নম্বর খুলে শিরোনাম মেলান |
AI-কে ARQ-এর অঙ্ক দিলে অনুমান আর রীতি আগেই বেঁধে দিন:
AI-এর উত্তর মানার আগে — চেকলিস্ট
ভাবনার প্রশ্ন
প্রতিটি প্রশ্ন নিয়ে নিজে কিছুক্ষণ ভাবুন — তারপর “→ উত্তর” চাপুন।
প্র ০১প্রতিটি link নিজেই নির্ভরযোগ্য হলে পুরো পথও নির্ভরযোগ্য — তাহলে TCP-র দরকার কী? আর উল্টো দিকে, TCP থাকলে link-এ ARQ কেন?
এই প্রশ্নের সবচেয়ে বিখ্যাত উত্তর ১৯৮৪ সালের একটি প্রবন্ধে — Jerome Saltzer, David Reed আর David Clark-এর “End-to-End Arguments in System Design”. তাঁদের যুক্তি: কোনো কাজ যদি শেষ প্রান্তের অ্যাপ্লিকেশন ছাড়া পুরোপুরি ঠিকভাবে করা না যায়, তবে নিচের স্তরে সেটি করা বড়জোর একটি গতি-বাড়ানোর কৌশল, নির্ভুলতার নিশ্চয়তা নয়।
কেন প্রতিটি link নির্ভরযোগ্য হলেও পুরো পথ নির্ভরযোগ্য নয়? কারণ ভুল হতে পারে link-এর বাইরে: router-এর মেমরিতে bit উল্টে যেতে পারে, buffer ভরে router packet ফেলে দিতে পারে (পর্ব ০৫), router নিজে বিকল হতে পারে, বা packet ভিন্ন পথে গিয়ে ক্রম উল্টে যেতে পারে। প্রতিটি link-এর ACK শুধু বলে “পাশের স্টেশন পেয়েছে” — “গন্তব্যের অ্যাপ পেয়েছে” নয়। কুরিয়ারের প্রতিটি হাব রসিদ দিলেও শেষ হাবের গুদামে পার্সেল হারালে প্রাপক কিছুই পাবেন না; তাই প্রাপকের নিজের স্বাক্ষর লাগে। ইন্টারনেটে সেই স্বাক্ষর TCP.
তাহলে link-এ ARQ কেন? গতির জন্য — এখানেই end-to-end যুক্তির দ্বিতীয় অংশ। ধরুন একটি Wi-Fi link-এ ১০% frame নষ্ট হয়, আর পুরো পথের RTT ২০০ ms. শুধু TCP-র ওপর ছাড়লে প্রতিটি loss ধরতে অন্তত একটি RTT বা আরও বেশি লাগবে, আর TCP loss দেখে পাঠানোর গতি কমাবে, যেন নেটওয়ার্কে ভিড়। অথচ সমস্যাটি ছিল শুধু একটি দুর্বল বেতার hop-এ। Link নিজে কয়েকশো মাইক্রোসেকেন্ডে আবার পাঠালে ওপরের TCP প্রায় কিছুই টের পায় না। তাই নিয়মটি দাঁড়ায়: link-এর ত্রুটি বেশি হলে link-এ ARQ, কম হলে নয় — Wi-Fi আর Ethernet-এর পার্থক্য ঠিক এটাই।
পুরোনো X.25 নেটওয়ার্ক প্রতিটি hop-এ পূর্ণ নির্ভরযোগ্যতা দিত (LAPB, HDLC-র একটি রূপ), কারণ তখনকার টেলিফোন লাইনে ত্রুটি অনেক বেশি ছিল। Fiber আসার পর এই খরচ অর্থহীন হয়ে যায়, আর ইন্টারনেটের “সরল core, বুদ্ধিমান প্রান্ত” নকশা জয়ী হয়।
মূল উপলব্ধি: নির্ভুলতার নিশ্চয়তা আসে প্রান্ত থেকে প্রান্তে; link-স্তরের ARQ শুধু তখনই যুক্তিসংগত যখন link-এর ত্রুটি এত বেশি যে প্রান্তের সমাধান অনেক ধীর হয়ে যায়।
প্র ০২TFTP আজও stop-and-wait-এর মতো এক-এক block করে চলে — এত অদক্ষ নকশা কেন টিকে আছে, আর “Sorcerer's Apprentice” বাগ কী শিখিয়েছে?
TFTP (Trivial File Transfer Protocol, বর্তমান রূপ RFC 1350) UDP-র ওপর চলে আর মূল নকশায় ঠিক stop-and-wait: ৫১২ byte-এর একটি block পাঠানো, তার ACK এলে পরেরটি। block নম্বর থাকে, timeout হলে আবার পাঠানো হয়। অংশ ৪-এর সূত্র অনুযায়ী লম্বা পথে এটি ভয়ানক ধীর। তবু TFTP টিকে আছে, কারণ এর ব্যবহার অন্যখানে: নেটওয়ার্ক থেকে কম্পিউটার boot করা (PXE), router-switch-এর firmware বা configuration ফাইল আদান-প্রদান, ছোট embedded যন্ত্র। এসব কাজ সাধারণত একই LAN-এ, যেখানে a খুব ছোট আর অংশ ৪-এর অঙ্ক ৩ অনুযায়ী stop-and-wait-এর efficiency প্রায় পূর্ণ। আর boot-এর মুহূর্তে যন্ত্রের ROM-এ খুব অল্প জায়গা থাকে — পূর্ণ TCP stack রাখা কঠিন, কিন্তু কয়েকশো লাইনের TFTP সহজেই ধরে।
সরল নকশাতেও সূক্ষ্ম বাগ লুকিয়ে থাকতে পারে। TFTP-র প্রথম দিকের নিয়মে প্রেরক নকল ACK পেলেও পরের block পাঠাত। ধরুন block 5-এর ACK দেরিতে আসায় timeout হলো আর block 5 আবার গেল। এবার প্রাপক দুটি block 5 পেয়ে দুটি ACK পাঠায়; প্রেরক প্রতিটি ACK-এর জবাবে block 6 পাঠায় — দুটি block 6, তার দুটি ACK, দুটি block 7… সেখান থেকে প্রতিটি block দুবার যেতে থাকে, শেষ পর্যন্ত। এর নাম দেওয়া হয় “Sorcerer's Apprentice Syndrome” (জাদুকরের শিষ্য যে ঝাড়ু থামাতে না পেরে কেটে দুটি বানায়, আর দুটিই পানি টানতে থাকে)। RFC 1123 এর সমাধান দেয়: নকল ACK পেলে কিছুই আবার পাঠাবেন না — অংশ ৩-এর “দেরিতে আসা ACK” সমস্যার ঠিক এই শিক্ষা।
পরে TFTP-র জন্য বড় block-আকার আর ২০১৫ সালে একটি “windowsize” option (RFC 7440) প্রস্তাবিত হয় — অর্থাৎ stop-and-wait থেকে sliding window-এ যাওয়ার পথ খোলা হয়, যাতে boot image দ্রুত নামে।
মূল উপলব্ধি: “অদক্ষ” নকশা যথেষ্ট ভালো হতে পারে যখন a ছোট আর সরলতা মূল্যবান। আর ARQ-এর প্রতিটি নিয়ম — নকল চেনা, দেরিতে আসা ACK উপেক্ষা — বাস্তবের বাগ থেকে শেখা।
প্র ০৩Sequence number-এর bit বাড়ালেই তো window বাড়ে — তাহলে সব protocol বিশাল নম্বর রাখে না কেন? “নম্বর ঘুরে আসা” বাস্তবে কতটা বিপজ্জনক?
প্রথম খরচ header-এর জায়গা। প্রতিটি frame-এ নম্বর যায় — ডেটা frame-এ নিজের নম্বর, piggyback করলে ACK নম্বরও। ১৯৭০-এর দশকের ধীর লাইনে, যখন HDLC আর তার আত্মীয়রা নকশা হয়, প্রতিটি bit মূল্যবান ছিল। তাই সাধারণ ক্ষেত্রে ৩ bit (window ৭), আর লম্বা উপগ্রহ link-এর জন্য ঐচ্ছিক ৭ bit (window ১২৭)। দ্বিতীয় খরচ মেমরি: SR-এ প্রাপককে window-এর সমান frame জমিয়ে রাখতে হয়, আর প্রেরককে প্রতিটি অস্বীকৃত frame-এর কপি আর timer রাখতে হয়। তৃতীয়ত, window প্রয়োজনের চেয়ে বড় হলে লাভ নেই — অংশ ৭ অনুযায়ী W ≥ 1 + 2a হলেই link পূর্ণ।
কিন্তু নম্বর ছোট হলে বিপদ আসে অংশ ৫–৬-এর প্রমাণ থেকে: পুরোনো একটি নকল যদি নেটওয়ার্কে দীর্ঘক্ষণ আটকে থেকে ঠিক তখন পৌঁছায় যখন একই নম্বর আবার ব্যবহার হচ্ছে, প্রাপক তাকে নতুন ভেবে নেবে। একটি তারের link-এ frame-এর ক্রম বদলায় না আর পথে আটকেও থাকে না, তাই window-এর সীমাই যথেষ্ট সুরক্ষা। কিন্তু ইন্টারনেটে packet ভিন্ন পথে যেতে পারে, router-এর queue-তে বসে থাকতে পারে।
TCP তাই ৩২ bit-এর byte-নম্বর রাখে — প্রায় ৪৩০ কোটি। ১৯৮০-র দশকের গতিতে এই নম্বর ঘুরে আসতে কয়েক ঘণ্টা লাগত, আর নেটওয়ার্কে কোনো packet অত সময় টেকে না। কিন্তু ১০ Gbps-এ হিসাব বদলে যায়: ২৩২ byte ≈ ৩.৪ × ১০১০ bit, যা ১০১০ bit/s-এ মাত্র প্রায় ৩.৪ সেকেন্ডে শেষ! অর্থাৎ কয়েক সেকেন্ড দেরিতে আসা একটি পুরোনো segment নতুন ডেটার জায়গায় বসে যেতে পারে। এজন্য TCP-তে timestamp option আর PAWS (Protection Against Wrapped Sequences) কৌশল যোগ হয়েছে — নম্বর এক হলেও সময়ের ছাপ দেখে পুরোনোকে চেনা যায় (বর্তমান মানদণ্ড RFC 7323). নতুন protocol QUIC আরও এগিয়ে গেছে: প্রতিটি packet-এ নতুন নম্বর, কখনো পুনর্ব্যবহার নয় (পর্ব ৩৩)।
মূল উপলব্ধি: নম্বরের আকার ঠিক হয় তিনটি জিনিসে — প্রয়োজনীয় window (1 + 2a), header-এর খরচ, আর পুরোনো নকল পথে কতক্ষণ বেঁচে থাকতে পারে। গতি বাড়লে একসময়ের “যথেষ্ট বড়” নম্বরও ছোট হয়ে যায়।
প্র ০৪HDLC এখন প্রায় কোথাও সরাসরি চোখে পড়ে না — তবু পরীক্ষায় কেন আসে? এর বংশধরেরা আজ কোথায়?
HDLC-র গল্প শুরু IBM-এর SDLC দিয়ে, ১৯৭০-এর দশকে mainframe আর terminal-এর মধ্যে যোগাযোগের জন্য। ISO সেটিকে সাধারণীকরণ করে HDLC নামে মানদণ্ড বানায়। এরপর আন্তর্জাতিক টেলিযোগাযোগ সংস্থাগুলো নিজেদের প্রয়োজনে এর নানা রূপ নেয়: X.25 প্যাকেট নেটওয়ার্কে LAPB (ABM mode-এ দুই প্রান্ত সমান), ISDN-এর signalling চ্যানেলে LAPD, মোবাইল নেটওয়ার্কের কিছু signalling-এ LAPDm, আর modem-এর error correction-এ LAPM. ইন্টারনেটের PPP-ও HDLC-ধাঁচের framing নিয়েছে — flag 0x7E, address 0xFF আর control 0x03-এর মতো ঘর এখনো সেখানে।
পরীক্ষায় HDLC আসে কারণ এটি একটি পাঠ্যবইয়ের মডেলের সম্পূর্ণ বাস্তব উদাহরণ: bit stuffing দিয়ে framing, I/S/U তিন ধরনের frame, piggyback করা N(R), RR/RNR দিয়ে flow control, REJ দিয়ে Go-Back-N আর SREJ দিয়ে selective repeat, ৩ বা ৭ bit-এর নম্বর। একটি protocol পড়লেই এই পর্বের প্রায় সব ধারণা একসাথে দেখা যায়।
আজ কোথায়? সাধারণ মানুষের চোখে প্রায় নেই। কিন্তু অনেক পুরোনো লিজড লাইন, শিল্প-কারখানার নিয়ন্ত্রণ নেটওয়ার্ক আর টেলিকম যন্ত্রের ভেতরে HDLC বা তার রূপ এখনো চলে; কিছু router-এর serial interface-এর ডিফল্ট encapsulation-ও HDLC-ভিত্তিক (Cisco-র নিজস্ব রূপ, যা মানদণ্ডের হুবহু নয়)। আর ধারণাগুলো ছড়িয়ে আছে সর্বত্র: Wi-Fi-র block ACK, Bluetooth-এর link স্তর, মোবাইলের radio link control — সবখানে sequence নম্বর, window আর selective retransmission.
বাংলাদেশের দিক থেকে একটি বাস্তব সংযোগ: বাড়ির broadband-এ PPPoE চালু থাকলে আপনার router প্রতিদিন PPP-র LCP আর authentication চালাচ্ছে — যার framing-এর পূর্বপুরুষ HDLC.
মূল উপলব্ধি: নির্দিষ্ট protocol বদলায়, ধারণা থাকে। HDLC শেখা মানে একটি পুরোনো মানদণ্ড মুখস্থ করা নয় — framing, ARQ আর flow control-এর এমন একটি নকশা পড়া যার টুকরো আজকের প্রায় প্রতিটি link protocol-এ আছে।
প্র ০৫Go-Back-N “অপচয়ী”, Selective Repeat “দক্ষ” — তাহলে কেউ GBN বেছে নেয় কেন? কোন পরিস্থিতিতে কোনটি?
Efficiency-র টেবিল দেখলে মনে হয় SR সবসময় জেতে। কিন্তু একজন প্রকৌশলী শুধু efficiency দেখেন না — দেখেন খরচ, জটিলতা আর পরিস্থিতি।
GBN-এর পক্ষে: প্রাপক অত্যন্ত সরল — একটিমাত্র “পরের চাই” নম্বর, কোনো buffer নেই, ক্রম সাজানোর ঝামেলা নেই। যখন প্রাপক একটি ছোট, সস্তা যন্ত্র (পুরোনো terminal, সেন্সর, ছোট microcontroller) আর মেমরি দামি, তখন এটি বড় সুবিধা। Cumulative ACK আরেকটি উপহার দেয়: একটি ACK হারালেও পরের ACK আগেরটির কাজ করে দেয়, তাই ACK-এর পথ দুর্বল হলেও কাজ চলে। আর link-এ ত্রুটি খুব কম হলে (অংশ ৭-এর টেবিলে a ছোট বা p প্রায় শূন্য) GBN আর SR-এর পার্থক্য প্রায় নেই — তখন সরলটিই যুক্তিসংগত।
SR-এর পক্ষে: লম্বা আর ত্রুটিপূর্ণ link — বিশেষত উপগ্রহ আর বেতার। a = ১২.৫, p = ১%, W = ১২৭-এ SR ৯৯% রাখে, GBN নামে প্রায় ৭৯%-এ (অংশ ৭-এর আউটপুট)। bandwidth যেখানে দামি, সেখানে এই ২০% অনেক টাকা। এজন্যই HDLC-তে SREJ রাখা হয়েছিল, আর আধুনিক Wi-Fi-র block ACK কোন frame পৌঁছেছে তার একটি bitmap পাঠায় — selective repeat-এর আধুনিক রূপ।
বাস্তবের সমাধান প্রায়ই মিশ্র। TCP শুরুতে ছিল প্রায় GBN-ধাঁচের (cumulative ACK), কিন্তু প্রাপক ক্রমের বাইরের ডেটা রেখে দিত। ১৯৯৬ সালে SACK (RFC 2018) এসে প্রাপককে জানানোর সুযোগ দিল ঠিক কোন টুকরো পেয়েছে, আর আজকের প্রায় সব operating system-এ এটি চালু থাকে — ফলে TCP কার্যত SR-এর সুবিধা পায়, cumulative ACK-এর দৃঢ়তা না হারিয়ে। পরীক্ষায় “TCP কোনটি — GBN না SR?” প্রশ্নের নিরাপদ উত্তর তাই “দুটির মিশ্রণ”।
মূল উপলব্ধি: “সেরা protocol” বলে কিছু নেই — আছে নির্দিষ্ট a, p, মেমরি আর জটিলতার বাজেটের জন্য সেরা। সূত্রগুলো সেই সিদ্ধান্তকে সংখ্যায় বাঁধার হাতিয়ার।
অনুশীলন
খাতা-কলম আর ক্যালকুলেটর নিন — সময়রেখা এঁকে, প্রতিটি সংখ্যার একক লিখে হিসাব করুন।
-
হাতে হিসাব: ১০ Mbps-এর একটি link, দৈর্ঘ্য ৩,০০০ km (s = ২ × ১০৮ m/s), frame ১,২৫০ byte. (ক) Stop-and-wait-এর efficiency আর throughput কত? (খ) Link পুরো ব্যবহার করতে কমপক্ষে কত window লাগবে? (গ) GBN আর SR-এর জন্য কত bit-এর sequence number লাগবে? (ঘ) ৩ bit নিয়ে GBN-এর W = ৭ হলে efficiency কত?
L = ১০,০০০ bit; Ttrans = ১০৪ ÷ ১০৭ = ১ ms; Tprop = ৩ × ১০৬ ÷ ২ × ১০৮ = ১৫ ms; a = ১৫.
(ক) U = ১ ÷ (১ + ৩০) = ১/৩১ ≈ ৩.২৩%; throughput ≈ ১০ Mbps × ০.০৩২৩ ≈ ৩২২.৬ kbps. (খ) W ≥ ১ + ২a = ৩১. (গ) GBN: 2m − 1 ≥ ৩১ ⇒ m = ৫ (ঠিক ৩১); SR: 2m−1 ≥ ৩১ ⇒ m = ৬ (৩২)। (ঘ) U = ৭/৩১ ≈ ২২.৬%.
-
Trace by hand: (ক) HDLC প্রাপক দুই flag-এর মাঝে পেল
011111001111101. আসল ডেটা কী? (খ) PPP-র নিয়মে7E 7D 01ডেটার frame কেমন হবে (দুই পাশের flag-সহ)?(ক) বাঁ থেকে পড়ুন:
0 11111— পাঁচটি 1, পরের0stuffed, মুছুন। তারপর0 11111— আবার পাঁচটি 1, পরের0মুছুন। শেষে1. ফল0111110111111(১৩ bit). খেয়াল করুন, আসল ডেটায় শেষে ছয়টি টানা 1 আছে — ডেটায় তা থাকতেই পারে; প্রেরক stuff করেছিল বলেই লাইনে ছয়টি টানা 1 যায়নি।(খ)
7E→7D 5E,7D→7D 5D,01অপরিবর্তিত: frame =7E 7D 5E 7D 5D 01 7E. -
আউটপুট অনুমান করুন: অংশ ৭-এর simulator-এ শেষের লুপটি বদলে শুধু
[[5]]দিলে (frame 5-এর প্রথম কপি হারায়) Go-Back-N আর Selective Repeat-এর লাইনে কত transmission আর কোন সময়ে শেষ দেখাবে? আগে হাতে হিসাব করুন, তারপর চালিয়ে মেলান।Frame 0–4 নির্বিঘ্নে যায়; 4 যায় t = ৫-এ, 5 যায় t = ৬-এ (হারায়), 6 আর 7 যায় t = ৭ ও ৮-এ। 5-এর timeout t = ১২-এ।
GBN: 6 আর 7 পৌঁছে ফেলে দেওয়া হয়; t = ১২, ১৩, ১৪-এ 5, 6, 7 আবার যায়; 7 পৌঁছায় t = ১৭-এ, ACK8 আসে t = ১৯-এ। ফল:
transmissions=11 done at t=19. SR: 6, 7 buffer-এ থাকে; শুধু 5 আবার যায় t = ১২-এ, পৌঁছায় t = ১৫-এ, ACK আসে t = ১৭-এ। ফল:transmissions=9 done at t=17. এখানে শেষের দিকে loss হওয়ায় SR সময়েও এগিয়ে। -
প্রমাণ লিখুন: m = ৩ bit-এর sequence number (0–7) নিয়ে কেউ Selective Repeat-এ W = ৫ নিল। একটি নির্দিষ্ট ঘটনাক্রম লিখুন যেখানে প্রাপক পুরোনো frame-কে নতুন ভেবে নেয়। W = ৪ হলে সেই ঘটনাক্রম কেন ব্যর্থ হয়?
প্রেরক 0, 1, 2, 3, 4 পাঠাল; প্রাপক পাঁচটিই পেল, ACK দিল, তার window সরে হলো {5, 6, 7, 0, 1}. সব ACK হারাল। প্রেরকের timeout — পুরোনো frame 0 আবার গেল। প্রাপকের window-এ 0 আছে, তাই সে এটিকে পরের চক্রের নতুন 0 ভেবে buffer-এ নিল — ভুল।
W = ৪ হলে প্রেরক পাঠায় 0–3, প্রাপকের নতুন window {4, 5, 6, 7}. পুরোনো 0, 1, 2 বা 3 যেটিই আবার আসুক, তা window-এর বাইরে — প্রাপক চেনে এটি নকল, ফেলে দিয়ে ACK আবার পাঠায়। দুই window মিলে ৮টি আলাদা নম্বর লাগে, আর 23 = ৮ — ঠিক যথেষ্ট; তাই W ≤ 2m−1 = ৪.
নিজেকে যাচাই করুন
ভুল হলে কারণসহ ব্যাখ্যা পাবেন, আবার চেষ্টাও করতে পারবেন।
ক্রমStop-and-wait-এ একটি ACK হারালে কী কী ঘটে — সঠিক ক্রমে সাজান (▲▼ চেপে সরান)
- প্রেরক seq 1-এর frame পাঠিয়ে timer চালু করে
- প্রাপক frame নেয়, ওপরের স্তরে দেয়, “ACK 0” পাঠায়
- ACK পথে হারিয়ে যায়
- Timer ফুরায়, প্রেরক seq 1-এর frame আবার পাঠায়
- প্রাপক seq 1 দেখে নকল চেনে, ফেলে দিয়ে আবার “ACK 0” পাঠায়
- প্রেরক ACK পেয়ে seq 0-এর পরের frame পাঠায়
HDLC bit stuffing-এ ডেটা 01111111 (একটি 0, তারপর সাতটি 1) পাঠালে flag-এর মাঝে কী যাবে?
- 01111111
- 011111011
- 011111101
- 0101010101010101
একটি link-এ frame-এর transmission time ২ ms আর একমুখী propagation delay ৪ ms. ত্রুটি না থাকলে stop-and-wait-এর efficiency কত?
- ৫০%
- ৩৩.৩%
- ২০%
- ১১.১%
৩ bit-এর sequence number (0–7) ব্যবহার করলে Go-Back-N-এ প্রেরকের সর্বোচ্চ window কত?
- ৮
- ৪
- ১
- ৭
৪ bit-এর sequence number (0–15) ব্যবহার করলে Selective Repeat-এ সর্বোচ্চ window কত?
- ৮
- ১৫
- ১৬
- ৪
একটি link-এ a = Tprop/Ttrans = ১২, আর sliding window W = ১০. ত্রুটিহীন অবস্থায় efficiency কত?
- ১০০%
- ৪০%
- ৮৩.৩%
- ৪%
তারের Ethernet-এ একটি frame-এর FCS মিলল না। প্রাপকের NIC সাধারণত কী করে?
- প্রেরককে NAK পাঠায়, প্রেরক সঙ্গে সঙ্গে আবার পাঠায়
- Frame ওপরের স্তরে দিয়ে দেয়, সাথে একটি সতর্কবার্তা
- চুপচাপ frame ফেলে দেয়; দরকার হলে ওপরের স্তর (যেমন TCP) আবার পাঠায়
- FCS ব্যবহার করে নষ্ট bit ঠিক করে নেয়
শব্দকোষ
লেখার মধ্যে ডটেড দাগ দেওয়া শব্দে মাউস রাখুন বা চাপুন — অর্থ দেখাবে। এই পর্বের সব নতুন শব্দ এখানে একসাথে:
মনে রাখুন
- Data link স্তর এক link-এর দুই প্রান্তে কাজ করে: framing, error control, flow control, MAC; উপস্তর LLC আর MAC.
- Framing: byte stuffing (FLAG/ESC; PPP-তে 7E → 7D 5E) আর bit stuffing (পাঁচটি 1-এর পর 0; flag 01111110).
- ARQ = ACK + timer + sequence number; stop-and-wait-এ ১ bit যথেষ্ট, efficiency U = 1/(1 + 2a), ত্রুটিসহ (1 − p)/(1 + 2a).
- GBN: cumulative ACK, সব আবার পাঠানো, W ≤ 2m − 1. SR: আলাদা ACK, buffer, শুধু হারানোটি, W ≤ 2m−1. Efficiency min(1, W/(1 + 2a)).
- HDLC আর PPP এই ধারণার বাস্তব রূপ; Ethernet ARQ করে না, Wi-Fi করে — link-এর ত্রুটির হার অনুযায়ী।
আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ
- পর্ব ১১ · Multiple access — ALOHA, CSMA/CD আর CSMA/CAপরবর্তী পর্বভাগ করা মাধ্যমে কে কখন পাঠাবে — MAC উপস্তরের কাজ।
- পর্ব ০৫ · Delay, loss আর throughputভিত্তিTransmission আর propagation delay, bandwidth-delay product — এই পর্বের a-র উৎস।
- কম্পিউটার নেটওয়ার্ক · কোর্স হোম৬২টি পর্বপুরো কোর্সের রোডম্যাপ — কোন পর্ব কখন।
- ডেটা কমিউনিকেশনসহজ শুরুকম্পিউটার ফান্ডামেন্টালস কোর্সে ডেটা পাঠানোর প্রাথমিক ধারণা।
- অপারেটিং সিস্টেম · IPCপাশের ট্র্যাকsocketpair, pipe আর socket — এই পর্বের C প্রোগ্রামের ভিত্তি।