পাঠ ২৩ · ৫৭-এর মধ্যে · মডিউল ৫

UDP — কানেকশনলেস ট্রান্সপোর্ট

UDP — connectionless transport
৭ মিনিট পড়া মধ্যবর্তী · Intermediate Python কোডসহ সম্পূর্ণ বাংলায়

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

  • UDP-এর মূল বৈশিষ্ট্য — কানেকশনলেস, অবিশ্বাস্য, ন্যূনতম হেডার
  • UDP কোথায় সবচেয়ে ভালো কাজ করে ও কেন
  • নির্ভরযোগ্যতা কেন সবসময় কাম্য নয় — একটি গুরুত্বপূর্ণ ডিজাইন-দর্শন
  • Python দিয়ে ডেটাগ্রাম হারানোর একটি নির্ধারিত (deterministic) সিমুলেশন

১ · UDP কী

UDPUser Datagram Protocolএকটি ন্যূনতম, কানেকশনলেস ট্রান্সপোর্ট-লেয়ার প্রোটোকল — কোনো হ্যান্ডশেক, ACK, বা রিট্রান্সমিশন ছাড়াই ডেটাগ্রাম পাঠায়। (User Datagram Protocol) হলো ট্রান্সপোর্ট লেয়ারের দুটি প্রধান প্রোটোকলের একটি (অন্যটি TCP, L24-27)। এর নকশার দর্শন — যত সম্ভব সরল ও দ্রুত রাখা, নির্ভরযোগ্যতার কোনো প্রতিশ্রুতি না দিয়ে।

কানেকশনলেস
কোনো হ্যান্ডশেক নেই, কোনো established সেশন-স্টেট নেই — প্রতিটি ডেটাগ্রাম স্বাধীন।
অবিশ্বাস্য
কোনো acknowledgment বা retransmission নেই — একটি হারানো ডেটাগ্রাম কেবল হারিয়েই যায়।
ন্যূনতম হেডার
মাত্র ৮ বাইট (সোর্স/ডেস্টিনেশন পোর্ট + দৈর্ঘ্য + চেকসাম) — কোনো ফ্লো/কনজেশন কন্ট্রোলের বাড়তি ওভারহেড নেই।

২ · UDP কোথায় সবচেয়ে ভালো কাজ করে

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

"অবিশ্বাস্য" মানে "খারাপ" নয় — নির্ভরযোগ্যতা প্রয়োগ করতেও (ACK পাঠানো, টাইমআউট ট্র্যাক করা, রিট্রান্সমিট করা) সময় ও ওভারহেড লাগে। যেসব ক্ষেত্রে দেরি করে-হলেও-সঠিক ডেটা দেরিতে-সঠিক ডেটার চেয়ে খারাপ (যেমন লাইভ ভিডিও কল), সেখানে UDP-এর "কোনো গ্যারান্টি নেই" আচরণটাই আসলে সঠিক পছন্দ।

Python
# UDP-স্টাইল ডেটাগ্রাম পাঠানোর সিমুলেশন — টয় ইন-মেমরি ডেটা, একটি নির্ধারিত (deterministic) ড্রপ প্যাটার্ন
# (এলোমেলো/random নয় — যাতে ফলাফল প্রতিবার একই হয়)

drop_pattern = [False, False, True, False, True, False, False]  # সূচক অনুযায়ী কোন ডেটাগ্রাম "হারিয়ে যাবে"

def send_datagram(datagrams, drop_pattern):
    """প্রতিটি ডেটাগ্রাম পাঠানোর চেষ্টা করে; drop_pattern অনুযায়ী কিছু হারিয়ে যায় —
    UDP-এর মতো, কোনো retry/retransmission লজিক ছাড়াই।"""
    results = []
    for i, data in enumerate(datagrams):
        dropped = drop_pattern[i % len(drop_pattern)]
        status = "হারিয়ে গেছে (কোনো retransmission নেই)" if dropped else "পৌঁছেছে"
        results.append((data, status))
    return results

datagrams = [f"ডেটাগ্রাম #{i}" for i in range(7)]
results = send_datagram(datagrams, drop_pattern)

print("UDP-স্টাইল সেন্ডিং ফলাফল:")
for data, status in results:
    print(f"  {data}: {status}")

delivered = sum(1 for _, status in results if status == "পৌঁছেছে")
lost = len(results) - delivered
print(f"\nমোট পাঠানো: {len(datagrams)} | পৌঁছেছে: {delivered} | হারিয়েছে: {lost}")
print("লক্ষ্য করুন — sender হারানো ডেটাগ্রাম সম্পর্কে কিছুই জানে না বা পুনরায় পাঠানোর চেষ্টা করে না, এটিই UDP-এর মূল আচরণ।")

    
এখানে drop_pattern একটি নির্ধারিত (fixed) তালিকা — এলোমেলো নয় — যাতে কোড প্রতিবার একই ফলাফল দেয় ও শিক্ষার্থী নিশ্চিতভাবে যাচাই করতে পারে কোন ইনডেক্সগুলো হারানো হয়েছে। বাস্তব নেটওয়ার্কে প্যাকেট হারানো অনির্ধারিত (কনজেশন, বিট এরর, বাফার ওভারফ্লো ইত্যাদির কারণে), কিন্তু এখানে ধারণাটি স্পষ্টভাবে দেখানোর জন্য ইচ্ছাকৃতভাবে নির্ধারিত রাখা হয়েছে।
মূল কথা · Key takeaway

UDP ইচ্ছাকৃতভাবে "বোকা ও দ্রুত" — এটি নির্ভরযোগ্যতার কোনো দায়িত্ব নেয় না, ফলে ন্যূনতম ওভারহেডে সর্বোচ্চ গতি দেয়। L24-২৭-এ আমরা দেখব TCP ঠিক বিপরীত পথে যায় — হ্যান্ডশেক, সিকোয়েন্স নাম্বার, ACK, ফ্লো ও কনজেশন কন্ট্রোল দিয়ে নির্ভরযোগ্যতা তৈরি করে, কিছুটা গতির বিনিময়ে।

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

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

প্র ০১ একটি লাইভ ভিডিও কলে একটি হারানো প্যাকেট রিট্রান্সমিট করা কেন প্রায়ই লাভজনক নয়?

ততক্ষণে ভিডিও স্ট্রিম আরও কয়েকটি ফ্রেম এগিয়ে গেছে — রিট্রান্সমিট করা পুরোনো ফ্রেমটি ফিরে আসার সময় সেটি আর "বর্তমান" থাকে না। সেই ফ্রেমের জন্য অপেক্ষা করলে পুরো স্ট্রিম আটকে যাবে (বাফারিং/স্টাটার), যা একটি সাময়িক ভিজ্যুয়াল গ্লিচের চেয়ে অভিজ্ঞতার জন্য অনেক বেশি খারাপ।

প্র ০২ DNS সাধারণত UDP ব্যবহার করে কেন, যদিও এটি অবিশ্বাস্য?

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

প্র ০৩ যদি একটি অ্যাপ্লিকেশনের UDP-এর গতি দরকার কিন্তু কিছু নির্ভরযোগ্যতাও দরকার হয়, তাহলে কী করা যেতে পারে?

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

অনুশীলন

  1. চিন্তা করুন: উপরের কোড সেলে drop_pattern পরিবর্তন করে সবগুলো মান False করুন এবং Run চেপে দেখুন ফলাফল কীভাবে বদলায়।

    সবগুলো ডেটাগ্রাম "পৌঁছেছে" দেখাবে, delivered = 7, lost = 0। এটি দেখায় যে drop_pattern-ই একমাত্র জিনিস যা নির্ধারণ করে কোনটি হারায় — বাস্তব নেটওয়ার্কে এই "প্যাটার্ন" আসলে অনির্ধারিত নেটওয়ার্ক পরিস্থিতির (কনজেশন, ইন্টারফেরেন্স) ফল।

  2. পরীক্ষা করুন: datagrams-এর সংখ্যা ১৫টিতে বাড়ান (এখনও ৭-উপাদানের drop_pattern ব্যবহার করে, যা i % len(drop_pattern)-এর মাধ্যমে পুনরাবৃত্তি হবে) এবং লক্ষ্য করুন প্যাটার্নটি কীভাবে চক্রাকারে পুনরাবৃত্তি হয়।

    যেহেতু i % len(drop_pattern) ব্যবহার করা হয়েছে, ৭তম ডেটাগ্রামের পর প্যাটার্নটি আবার শুরু থেকে পুনরাবৃত্তি হবে (ইনডেক্স ৭ = ইনডেক্স ০-এর মতোই আচরণ করবে, ইত্যাদি) — মোট ১৫টির মধ্যে হারানোর সংখ্যা এই পুনরাবৃত্তি অনুযায়ী গণনা করা যায়।

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

আগের পাঠ
L22 · ট্রান্সপোর্ট লেয়ার পরিচিতি — পোর্ট ও মাল্টিপ্লেক্সিং