পাঠ ০৯ · ৫১-এর মধ্যে · মডিউল ২
Home / Courses / System Design / TCP বনাম UDP

TCP বনাম UDP ও নেটওয়ার্ক লেয়ার বেসিকস

TCP vs UDP & network layer basics
৮ মিনিট পড়া মধ্যম · Intermediate Python কোডসহ সম্পূর্ণ বাংলায়

এই পাঠে যা শিখবেন

  • TCP কীভাবে reliability নিশ্চিত করে — connection setup, acknowledgment, retransmission, ordering
  • UDP কেন কোনো গ্যারান্টি না দিয়েও ব্যাপকভাবে ব্যবহৃত হয়
  • কোন পরিস্থিতিতে TCP বেছে নেবেন, কোনটায় UDP
  • নেটওয়ার্ক লেয়ারের সংক্ষিপ্ত পরিচিতি
  • Python দিয়ে "TCP-like retry" বনাম "UDP-like fire-and-forget" আচরণ সিমুলেট করা

১ · TCP — নির্ভরযোগ্যতার মূল্য

TCPTransmission Control Protocolএকটি কানেকশন-ওরিয়েন্টেড ট্রান্সপোর্ট-লেয়ার প্রোটোকল যা প্রতিটি প্যাকেটের ডেলিভারি নিশ্চিত করে — হারিয়ে গেলে পুনরায় পাঠায় (retransmission), এবং সঠিক ক্রমে ডেটা পৌঁছে দেয়। যোগাযোগ শুরুর আগে একটি "3-way handshake" দিয়ে দুই প্রান্তের মধ্যে একটি কানেকশন প্রতিষ্ঠা করে। প্রতিটি পাঠানো প্যাকেটের জন্য প্রাপক একটি ACK (acknowledgment) পাঠায়; নির্দিষ্ট সময়ের মধ্যে ACK না পেলে প্রেরক ধরে নেয় প্যাকেটটি হারিয়ে গেছে এবং সেটি আবার পাঠায় (retransmission)। প্যাকেটগুলো নেটওয়ার্কে বিভিন্ন পথে গিয়ে বিশৃঙ্খল ক্রমে পৌঁছাতে পারে — TCP সিকোয়েন্স নম্বর দিয়ে সেগুলো আবার সঠিক ক্রমে সাজায়।

এই সবকিছুর মূল্য হলো ওভারহেড — হ্যান্ডশেক, ACK আদান-প্রদান, এবং প্রয়োজনে পুনঃপ্রেরণ সময় নেয়। কিন্তু HTTP-এর মতো প্রোটোকল যেখানে ডেটার প্রতিটি বাইট নির্ভুল হওয়া দরকার (একটি ওয়েবপেজের কোনো অংশ হারিয়ে গেলে চলবে না), সেখানে এই নিশ্চয়তা অপরিহার্য — তাই REST, gRPC, WebSocket (L07, L08) — সবই TCP-এর উপর চলে।

২ · UDP — গতির জন্য গ্যারান্টি বিসর্জন

UDPUser Datagram Protocolএকটি কানেকশনলেস ট্রান্সপোর্ট-লেয়ার প্রোটোকল — কোনো হ্যান্ডশেক নেই, কোনো ডেলিভারি বা ক্রমের গ্যারান্টি নেই, কিন্তু ওভারহেড অনেক কম, তাই দ্রুত। কোনো কানেকশন প্রতিষ্ঠা করে না, কোনো ACK আশা করে না, এবং হারিয়ে যাওয়া প্যাকেট পুনরায় পাঠায় না। প্রেরক শুধু ডেটা পাঠিয়ে দেয় এবং প্রাপকের কাছে পৌঁছাল কি না তা নিয়ে মাথা ঘামায় না — একে বলা হয় fire-and-forget।

এটি অদ্ভুত মনে হতে পারে — ডেটা হারিয়ে গেলে সমস্যা নয়? আসলে অনেক ক্ষেত্রে দেরিতে আসা ডেটা হারানো ডেটার চেয়েও খারাপ। যেমন — একটি ভিডিও কলে যদি একটি ফ্রেম হারিয়ে যায়, TCP-এর মতো সেটির জন্য অপেক্ষা করে retransmission করলে পুরো কলটাই থমকে যাবে (পুরনো একটি ফ্রেমের জন্য অপেক্ষা করে বর্তমান মুহূর্ত মিস করার চেয়ে সেই একটি ফ্রেম বাদ দিয়ে এগিয়ে যাওয়া ভালো)। এই কারণে DNS কোয়েরি (L05), ভিডিও/অডিও স্ট্রিমিং, VoIP কল, অনলাইন গেমিং, এবং আধুনিক QUIC/HTTP3 প্রোটোকল UDP-এর উপর ভিত্তি করে তৈরি (QUIC নিজে UDP-এর উপর নিজস্ব হালকা reliability লেয়ার যোগ করে TCP-এর কিছু ওভারহেড এড়িয়ে যায়)।

TCP
কানেকশন-ওরিয়েন্টেড, রিলায়েবল, অর্ডারড — HTTP, ফাইল ট্রান্সফার, ইমেইল।
UDP
কানেকশনলেস, গ্যারান্টিহীন, দ্রুত — DNS, ভিডিও/ভয়েস, গেমিং, QUIC।
সিদ্ধান্তের মূল প্রশ্ন

"এই ডেটার একটি অংশ হারিয়ে গেলে কি পুরো সিস্টেম ভুল ফলাফল দেবে (TCP দরকার), নাকি সামান্য কোয়ালিটি কমবে কিন্তু চলতে থাকবে (UDP গ্রহণযোগ্য)?" — একটি ব্যাংক ট্রানজেকশনের একটি বাইট হারালে চলবে না (TCP), কিন্তু একটি ভিডিও কলে এক ফ্রেমের সামান্য পিক্সেলেশন হলে চলবে (UDP)।

৩ · নেটওয়ার্ক লেয়ার — সংক্ষিপ্ত পরিচিতি

TCP ও UDP উভয়ই ট্রান্সপোর্ট লেয়ারে কাজ করে — নেটওয়ার্ক যোগাযোগের একটি নির্দিষ্ট স্তর। এই কোর্সের ফোকাস এই স্তরের নিচের বিস্তারিত প্রযুক্তিগত দিকে নয়, তবে বড় ছবিটা জানা দরকারী:

অ্যাপ্লিকেশন লেয়ার
HTTP, DNS, WebSocket — যে প্রোটোকল অ্যাপ্লিকেশন সরাসরি ব্যবহার করে।
ট্রান্সপোর্ট লেয়ার
TCP ও UDP এখানে — এন্ড-টু-এন্ড ডেটা ডেলিভারি পরিচালনা করে।
নেটওয়ার্ক লেয়ার
IP — কোন পথে প্যাকেট রাউট হবে তা ঠিক করে (IP অ্যাড্রেসিং)।
লিংক লেয়ার
একই নেটওয়ার্কের মধ্যে সরাসরি ফিজিক্যাল/লজিক্যাল ডেটা ট্রান্সফার (Ethernet, Wi-Fi)।
প্রেরক Sender প্যাকেট হারিয়ে গেল (TCP পথ) ACK না আসায় টাইমআউট no ACK -> timeout retransmit — আবার পাঠানো হয় UDP পথ fire-and-forget প্যাকেট হারালে — কিছুই হয় না no retry, প্রেরক জানেও না
একই প্যাকেট-লস পরিস্থিতিতে TCP পুনরায় পাঠানোর চেষ্টা করে, UDP সেই লস উপেক্ষা করে এগিয়ে যায়।

৪ · কোড দিয়ে দেখা — Retry বনাম Fire-and-Forget

নিচে একটি ডিটারমিনিস্টিক (নির্দিষ্ট, র‍্যান্ডম নয়) প্যাকেট-ড্রপ সিমুলেশন — কিছু নির্দিষ্ট প্যাকেট "হারিয়ে যায়" বলে ধরা হয়েছে। udp_like_send() একবার পাঠিয়েই থেমে যায় (হারানো প্যাকেট চিরতরে হারানো), আর tcp_like_send() হারানো প্যাকেট শনাক্ত করে পুনরায় পাঠায় যতক্ষণ না সব প্যাকেট নিশ্চিতভাবে পৌঁছায়।

Python
packets = ["P1", "P2", "P3", "P4", "P5", "P6", "P7", "P8"]
dropped_indices = {2, 5}  # নির্দিষ্ট (deterministic) — P3 ও P6ইনডেক্স ২ ও ৫ প্রথমবার হারিয়ে যাবে

def udp_like_send(packets, dropped_indices):
    received = []
    for i, p in enumerate(packets):
        if i in dropped_indices:
            print(f"  {p} হারিয়ে গেল — UDP পাত্তা দেয় না, এগিয়ে যায়")
            continue
        received.append(p)
        print(f"  {p} পৌঁছাল")
    return received

def tcp_like_send(packets, dropped_indices):
    received = []
    retries = 0
    for i, p in enumerate(packets):
        if i in dropped_indices:
            print(f"  {p} প্রথমবার হারিয়ে গেল — ACK আসেনি, TCP retransmit করবে")
            retries += 1
            print(f"  {p} রিট্রাই করে সফলভাবে পৌঁছাল (ACK পাওয়া গেল)")
        else:
            print(f"  {p} প্রথমবারেই পৌঁছাল (ACK পাওয়া গেল)")
        received.append(p)
    return received, retries

print("=== UDP-like (send once, accept loss) ===")
udp_received = udp_like_send(packets, dropped_indices)
print(f"\nUDP-like ফলাফল: {len(udp_received)}/{len(packets)} প্যাকেট পৌঁছাল -> {udp_received}")

print("\n=== TCP-like (retry until received) ===")
tcp_received, retry_count = tcp_like_send(packets, dropped_indices)
print(f"\nTCP-like ফলাফল: {len(tcp_received)}/{len(packets)} প্যাকেট পৌঁছাল -> {tcp_received}")
print(f"মোট রিট্রাই লাগল: {retry_count} বার")
print(f"সব প্যাকেট নিশ্চিতভাবে পৌঁছেছে কি? {len(tcp_received) == len(packets)}")

    
লক্ষ্য করুন — UDP-like পদ্ধতিতে ৮টির মধ্যে মাত্র ৬টি প্যাকেট পৌঁছায় (P3 ও P6 চিরতরে হারিয়ে যায়), কিন্তু TCP-like পদ্ধতি ২ বার রিট্রাই করে সবগুলো (৮/৮) প্যাকেট নিশ্চিতভাবে পৌঁছে দেয়। এই ২ বার রিট্রাই-এর মূল্যই হলো TCP-এর অতিরিক্ত লেটেন্সি ও ওভারহেড — বাস্তবে যত বেশি প্যাকেট হারায়, তত বেশি রিট্রাই ও তত বেশি বিলম্ব হয়।
মূল কথা · Key takeaway

TCP ও UDP কোনো একটি "ভালো" আর একটি "খারাপ" নয় — সঠিক নির্ভুলতা বনাম গতির মধ্যে একটি সচেতন ট্রেড-অফ। System Design ইন্টারভিউতে "এই সিস্টেমে কোনটা ব্যবহার করবেন" প্রশ্নের সঠিক উত্তর সবসময় নির্ভর করে ডেটা হারানোর পরিণতি কতটা গুরুতর তার উপর।

ভাবনার প্রশ্ন

প্রতিটি প্রশ্ন নিজে কিছুক্ষণ ভাবুন — তারপর "→ উত্তর" চাপুন।

প্র ০১ DNS (L05) কেন সাধারণত UDP ব্যবহার করে, যেখানে একটি ভুল/অসম্পূর্ণ উত্তর মারাত্মক মনে হতে পারে?

DNS কোয়েরি সাধারণত খুব ছোট (একটি সিঙ্গেল প্যাকেটে ফিট করে) এবং দ্রুত হওয়া জরুরি — প্রতিটি ওয়েবসাইট ভিজিটের আগে এটি ঘটে, তাই সামান্য বিলম্বও পুরো ব্রাউজিং অভিজ্ঞতা ধীর করে দেয়। যদি একটি DNS কোয়েরি হারিয়ে যায়, ক্লায়েন্ট অ্যাপ্লিকেশন লেয়ারে (রিজলভার) সহজেই সংক্ষিপ্ত টাইমআউটের পর আবার কোয়েরি পাঠাতে পারে — এটি TCP-এর হ্যান্ডশেক ও কানেকশন-মেইনটেনেন্স ওভারহেড ছাড়াই করা যায়। তবে বড় DNS রেসপন্স (যেমন DNSSEC-সহ) মাঝেমধ্যে TCP-তেও ফলব্যাক করে।

প্র ০২ QUIC/HTTP3 কেন UDP-এর উপর নিজস্ব reliability লেয়ার তৈরি করল, সরাসরি TCP ব্যবহার না করে?

TCP-এর reliability লজিক অপারেটিং সিস্টেম কার্নেলে গভীরভাবে বসানো এবং পরিবর্তন করা কঠিন/ধীর (বছরের পর বছর ধরে স্ট্যান্ডার্ডাইজড)। এছাড়া TCP-তে "head-of-line blocking" সমস্যা আছে — একটি স্ট্রিমের একটি প্যাকেট হারালে সেই কানেকশনের সব ডেটা ব্লক হয়ে যায়, এমনকি ভিন্ন, সম্পর্কহীন ডেটা স্ট্রিমের জন্যও। QUIC UDP-এর উপর নিজস্ব হালকা, দ্রুত-বিবর্তনযোগ্য reliability লজিক (অ্যাপ্লিকেশন লেয়ারে, তাই আপডেট করা সহজ) তৈরি করে, এবং একাধিক স্বাধীন স্ট্রিম সাপোর্ট করে যাতে একটির প্যাকেট-লস অন্যগুলোকে ব্লক না করে।

প্র ০৩ একটি অনলাইন মাল্টিপ্লেয়ার গেমে প্লেয়ারের অবস্থান আপডেট পাঠাতে UDP কেন TCP-এর চেয়ে ভালো পছন্দ?

গেমে প্রতি সেকেন্ডে বহুবার প্লেয়ারের নতুন অবস্থান পাঠানো হয় — প্রতিটি আপডেট আগেরটিকে অপ্রাসঙ্গিক করে দেয়। যদি একটি পুরনো পজিশন-প্যাকেট হারিয়ে যায় এবং TCP সেটি retransmit করার জন্য অপেক্ষা করায়, ততক্ষণে অনেক নতুন পজিশন ডেটা প্রস্তুত হয়ে গেছে — পুরনো ডেটার জন্য অপেক্ষা করা মানে পুরো গেমপ্লে বিলম্বিত করা, যেখানে সেই তথ্যটি ইতিমধ্যে অপ্রচলিত (stale)। UDP দিয়ে পুরনো প্যাকেট হারালে সমস্যা নেই — পরবর্তী (নতুন) পজিশন আপডেট দ্রুত চলে আসবে, এবং সামান্য একটি ফ্রেমের অসঙ্গতির চেয়ে তাৎক্ষণিকতা অনেক বেশি গুরুত্বপূর্ণ।

অনুশীলন

  1. চিন্তা করুন: একটি ফাইল-আপলোড ফিচার এবং একটি লাইভ ভিডিও কল — এই দুটির জন্য TCP বা UDP বেছে নিন এবং যুক্তি দিন।

    ফাইল আপলোডে প্রতিটি বাইট সঠিকভাবে পৌঁছানো আবশ্যক — একটি বাইট মিসিং মানে ফাইল করাপ্ট। তাই এখানে TCP অপরিহার্য। লাইভ ভিডিও কলে বিপরীত অগ্রাধিকার — সামান্য একটি ফ্রেম হারালে সামান্য গ্লিচ হবে, কিন্তু TCP-এর retransmission-জনিত বিলম্ব পুরো কলকে থমকে দেবে, যা ব্যবহারকারীর অভিজ্ঞতার জন্য আরও খারাপ। তাই ভিডিও কলে UDP (বা তার উপর তৈরি একটি প্রোটোকল) পছন্দনীয়।

  2. কোড এক্সটেন্ড করুন: উপরের কোড সেলে dropped_indices-এ আরও একটি ইনডেক্স (যেমন 7) যোগ করুন এবং retry_count কীভাবে বদলায় লক্ষ করুন। তারপর dropped_indices = set() (কোনো ড্রপ নেই) করলে কী হয়?

    dropped_indices-এ 7 যোগ করলে (যা P8-এর ইনডেক্স) retry_count ২ থেকে বেড়ে ৩ হবে, কারণ এখন তিনটি প্যাকেট (P3, P6, P8) প্রথমবার হারিয়ে গিয়ে রিট্রাই লাগবে। UDP-like তখন ৮টির মধ্যে ৫টি পৌঁছাবে। আর dropped_indices = set() (খালি সেট) করলে কোনো প্যাকেটই হারাবে না — তখন UDP ও TCP উভয়ই সবগুলো প্যাকেট প্রথমবারেই পৌঁছে দেবে এবং retry_count শূন্য (০) হবে, অর্থাৎ নেটওয়ার্ক নিখুঁত হলে TCP-এর অতিরিক্ত ওভারহেড কার্যত অদৃশ্য হয়ে যায়।

আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ

পূর্ববর্তী পাঠ
WebSockets ও রিয়েল-টাইম কমিউনিকেশন