পাঠ ০৯ · ৫৭-এর মধ্যে · মডিউল ৩
Home / Courses / Computer Networks / এরর ডিটেকশন

এরর ডিটেকশন — প্যারিটি, চেকসাম, CRC

Error detection — parity, checksum, CRC
৯ মিনিট পড়া মধ্যম · Intermediate Python কোডসহ সম্পূর্ণ বাংলায়

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

  • প্যারিটি বিট কীভাবে কাজ করে এবং এর সীমাবদ্ধতা কী
  • চেকসাম কীভাবে কাজ করে — IP/TCP/UDP-এর বাস্তব সংযোগ
  • CRC-এর মূল ধারণা — mod-2/XOR পলিনোমিয়াল ডিভিশন
  • Python-এ একটি বাস্তব mod2_divide, crc_encode, ও crc_check ইমপ্লিমেন্টেশন — যা রানটাইমে নিজেই এরর ধরে দেখায়

১ · প্যারিটি বিট

প্যারিটি বিটParity Bitডেটার সাথে যুক্ত একটি অতিরিক্ত বিট, যা মোট ১-বিটের সংখ্যা জোড় (even parity) বা বিজোড় (odd parity) রাখে — একক বিট-ফ্লিপ ধরার সবচেয়ে সহজ পদ্ধতি। সবচেয়ে সহজ এরর-ডিটেকশন কৌশল — ডেটার শেষে একটি অতিরিক্ত বিট যোগ করা হয় যাতে মোট ১-বিটের সংখ্যা জোড় (even parity) বা বিজোড় (odd parity) হয়। রিসিভার প্রাপ্ত বিট গুনে দেখে প্যারিটি ঠিক আছে কিনা।

সীমাবদ্ধতা — একটি বাস্তব দুর্বলতা

প্যারিটি বিট যেকোনো একক বিট-ফ্লিপ ধরতে পারে — কারণ তাতে প্যারিটি (জোড়/বিজোড়) বদলে যায়। কিন্তু যদি ঠিক দুটি বিট ফ্লিপ হয় (বা যেকোনো জোড়সংখ্যক বিট), মোট প্যারিটি অপরিবর্তিতই থাকে — এরর সম্পূর্ণ অলক্ষিত থেকে যায়। এই দুর্বলতাই চেকসাম ও CRC-এর মতো শক্তিশালী কৌশলের প্রয়োজনীয়তা তৈরি করে।

২ · চেকসাম

চেকসামChecksumডেটাকে ফিক্সড-সাইজ ব্লকে (যেমন ১৬-বিট শব্দ) ভাগ করে সব ব্লক যোগ করে তারপর কমপ্লিমেন্ট নিয়ে একটি চেক-ভ্যালু তৈরি করা। ডেটাকে ফিক্সড-সাইজ ব্লকে (যেমন ১৬-বিট শব্দ) ভাগ করে সবগুলো ব্লক যোগ করা হয়, তারপর যোগফলের কমপ্লিমেন্ট নেওয়া হয় — এটিই চেকসাম মান। এটি ঠিক এভাবেই বাস্তব IP, TCP ও UDP হেডারে ব্যবহৃত হয় — রিসিভার একই যোগফল হিসাব করে যাচাই করে। চেকসাম প্যারিটির চেয়ে শক্তিশালী (বেশিরভাগ এরর প্যাটার্ন ধরতে পারে), কিন্তু সব ধরনের এরর ধরতে পারে না — যেমন কিছু নির্দিষ্ট বিট-পুনর্বিন্যাস চেকসামকে বোকা বানাতে পারে।

৩ · CRC — Cyclic Redundancy Check

CRCCyclic Redundancy Checkডেটাকে একটি বাইনারি পলিনোমিয়াল হিসেবে ধরে একটি ফিক্সড জেনারেটর পলিনোমিয়াল দিয়ে mod-2 (XOR-ভিত্তিক) ডিভিশন করা হয়; অবশিষ্টাংশই চেক বিট হিসেবে যুক্ত হয়। ডেটাকে একটি বাইনারি পলিনোমিয়াল হিসেবে বিবেচনা করে, তাকে একটি ফিক্সড "জেনারেটর" পলিনোমিয়াল দিয়ে mod-2 (XOR-ভিত্তিক) ডিভিশন ব্যবহার করে ভাগ করা হয় — সাধারণ পাটিগণিতের বিয়োগের বদলে প্রতিটি ধাপে XOR ব্যবহার করা হয় (তাই "carry" বা "borrow"-এর কোনো ধারণা নেই)। ভাগশেষ (remainder)-ই চেক বিট হিসেবে মূল বার্তার সাথে যুক্ত হয়ে পাঠানো হয়। রিসিভার প্রাপ্ত সম্পূর্ণ বার্তা (চেক বিটসহ) একই জেনারেটর দিয়ে ভাগ করে — অবশিষ্টাংশ সম্পূর্ণ শূন্য হলে কোনো এরর ধরা পড়েনি, অন্যথায় করাপশন শনাক্ত হয়েছে। CRC সাধারণ চেকসামের চেয়ে অনেক বেশি শক্তিশালী এবং Ethernet ফ্রেম (M3/L11) ও ZIP ফাইলে বাস্তবে ব্যবহৃত হয়।

Python
# CRC -- বাস্তব mod-2 (XOR) পলিনোমিয়াল লং ডিভিশন
# নিচের ফাংশনগুলো একটি প্রকৃত অ্যালগরিদম -- কোনো ভাগশেষ হাতে-কষে বসানো হয়নি,
# কোড নিজেই রান-টাইমে হিসাব করে ফলাফল প্রিন্ট করছে।

def mod2_divide(dividend_bits, divisor_bits):
    """বাস্তব mod-2 (XOR-ভিত্তিক) পলিনোমিয়াল লং ডিভিশন।
    রিটার্ন করে ভাগশেষ (remainder), যার দৈর্ঘ্য = len(divisor_bits) - 1"""
    n = len(divisor_bits)
    work = list(dividend_bits)
    for i in range(len(work) - n + 1):
        if work[i] == '1':
            for j in range(n):
                work[i + j] = str(int(work[i + j]) ^ int(divisor_bits[j]))
    return ''.join(work[-(n - 1):]) if n > 1 else ''

def crc_encode(data_bits, generator_bits):
    """জেনারেটরের দৈর্ঘ্য - 1 সংখ্যক শূন্য যোগ করে ভাগশেষ বের করে,
    সেই ভাগশেষ-ই আসল চেক বিট হিসেবে ডেটার সাথে যুক্ত করা হয়।"""
    appended = data_bits + '0' * (len(generator_bits) - 1)
    remainder = mod2_divide(appended, generator_bits)
    return data_bits + remainder

def crc_check(received_bits, generator_bits):
    """প্রাপ্ত পুরো বার্তাকে (চেক বিটসহ) জেনারেটর দিয়ে ভাগ করে --
    ভাগশেষ সম্পূর্ণ শূন্য হলে কোনো এরর ধরা পড়েনি।"""
    remainder = mod2_divide(received_bits, generator_bits)
    return set(remainder) <= {'0'}

data = "1101011011"       # উদাহরণ ডেটা (টয় বিট-স্ট্রিং)
generator = "10011"       # উদাহরণ জেনারেটর পলিনোমিয়াল (CRC-4-এর মতো একটি টয় জেনারেটর)

encoded = crc_encode(data, generator)
check_bits = encoded[len(data):]

print("মূল ডেটা:      ", data)
print("জেনারেটর:      ", generator)
print("কম্পিউটেড চেক বিট:", check_bits, "(কোড নিজে হিসাব করেছে, হাতে বসানো নয়)")
print("পাঠানো বার্তা:  ", encoded)
print("রিসিভার-সাইড চেক (কোনো এরর ছাড়া):", crc_check(encoded, generator))

# ইচ্ছাকৃতভাবে একটি বিট ফ্লিপ করে করাপশন সিমুলেট করা
corrupted = list(encoded)
flip_index = 5
corrupted[flip_index] = '1' if corrupted[flip_index] == '0' else '0'
corrupted = ''.join(corrupted)

print(f"\nকরাপ্টেড বার্তা (বিট {flip_index} ফ্লিপড):", corrupted)
print("রিসিভার-সাইড চেক (এরর সহ, expect False):", crc_check(corrupted, generator))

    
ডেটা + শূন্য প্যাডিং জেনারেটর দিয়ে mod-2 ভাগ ভাগশেষ = চেক বিট পাঠানো বার্তা = ডেটা + চেক বিট রিসিভার: একই জেনারেটর দিয়ে আবার ভাগ — ভাগশেষ শূন্য? → OK, নাহলে → এরর
এনকোডে ভাগশেষ চেক বিট হিসেবে যুক্ত হয়, ডিকোডে আবার ভাগ করে ভাগশেষ শূন্য কিনা যাচাই করা হয় — অ-শূন্য ভাগশেষ মানেই ট্রান্সমিশনে এরর হয়েছে।
লক্ষ্য করুন — উপরের কোডে চেক বিটের প্রকৃত মান হাতে বসানো হয়নি; mod2_divide ফাংশনটি প্রকৃত XOR-ভিত্তিক লং ডিভিশন করে রান-টাইমে সেটি হিসাব করেছে। এরপর একটি বিট ইচ্ছাকৃতভাবে ফ্লিপ করে দেখানো হয়েছে যে করাপ্টেড বার্তায় crc_check সঠিকভাবে False রিটার্ন করে (এরর ধরা পড়েছে), অথচ আসল বার্তায় True রিটার্ন করে — এটিই CRC-এর প্রকৃত শক্তির প্রমাণ, কোনো অনুমানভিত্তিক উদাহরণ নয়।
মূল কথা · Key takeaway

প্যারিটি, চেকসাম ও CRC — তিনটিই একই মূল সমস্যার সমাধান করে (ট্রান্সমিশনে করাপশন ধরা), কিন্তু ভিন্ন ভিন্ন শক্তিমত্তায়। প্যারিটি সবচেয়ে সহজ কিন্তু দুর্বল, চেকসাম মাঝারি (বাস্তব TCP/IP-তে ব্যবহৃত), আর CRC সবচেয়ে শক্তিশালী (Ethernet, ZIP-এ ব্যবহৃত) — কারণ এর mod-2 পলিনোমিয়াল ডিভিশন বেশিরভাগ বাস্তব এরর-প্যাটার্ন (একক বিট, বার্স্ট এরর) নির্ভরযোগ্যভাবে ধরতে পারে। মনে রাখবেন — এরর ডিটেকশন শুধু বলে কিছু ভুল হয়েছে; পরের পাঠে (L10) আমরা দেখব কীভাবে Hamming কোড এরর কারেকশন-ও করতে পারে, পুনরায় পাঠানো ছাড়াই।

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

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

প্র ০১ CRC কি কখনো একটি ভুল বার্তাকে "সঠিক" বলে ভুল করে ফেলতে পারে?

তাত্ত্বিকভাবে হ্যাঁ — যদি করাপশনের ফলে তৈরি হওয়া ভুল পলিনোমিয়ালটি ঠিক জেনারেটর পলিনোমিয়ালের একটি গুণিতক (multiple) হয়ে যায়, তাহলে ভাগশেষ কাকতালীয়ভাবে শূন্য হয়ে যেতে পারে এবং এরর অলক্ষিত থেকে যাবে। তবে ভালোভাবে বাছাই করা জেনারেটর পলিনোমিয়াল (যেমন Ethernet-এ ব্যবহৃত CRC-32) ব্যবহারিকভাবে সব একক-বিট, ডাবল-বিট, এবং নির্দিষ্ট দৈর্ঘ্যের বার্স্ট এরর ১০০% ধরে ফেলে — শুধু অত্যন্ত বিরল, বিশেষ প্যাটার্নের এরর ফাঁকি দিতে পারে, যার সম্ভাবনা বাস্তবে উপেক্ষণীয়।

প্র ০২ চেকসাম বাস্তবে TCP/IP-তে ব্যবহৃত হয়, অথচ CRC বেশি শক্তিশালী — তাহলে TCP/IP কেন CRC ব্যবহার করে না?

চেকসাম গণনা করা (সরল যোগ ও কমপ্লিমেন্ট) CRC-এর mod-2 পলিনোমিয়াল ডিভিশনের চেয়ে অনেক দ্রুত ও সহজ — এবং IP/TCP লেয়ারে ধরে নেওয়া হয় যে নিচের ডেটা লিংক লেয়ার (Ethernet, M3/L11) ইতিমধ্যেই CRC দিয়ে বেশিরভাগ ট্রান্সমিশন এরর ফিল্টার করে ফেলেছে — তাই উপরের স্তরে হালকা চেকসামই যথেষ্ট, একটি অতিরিক্ত "সেফটি নেট" হিসেবে, সম্পূর্ণ এরর-ডিটেকশন দায়িত্ব হিসেবে নয়।

প্র ০৩ উপরের কোডে যদি ঠিক দুটি বিট ফ্লিপ করা হয় (একটির বদলে), CRC কি তারপরও এরর ধরতে পারবে?

প্রায় নিশ্চিতভাবেই হ্যাঁ — CRC-এর শক্তি প্যারিটির থেকে ভিন্ন যে এটি শুধু "মোট ১-বিটের সংখ্যা জোড়/বিজোড়" গোনে না, বরং পুরো বিট-প্যাটার্নকে একটি পলিনোমিয়াল হিসেবে বিবেচনা করে ভাগ করে — তাই একাধিক বিট ফ্লিপেও (যতক্ষণ না সেটি ঠিক জেনারেটরের গুণিতক তৈরি করে) ভাগশেষ অ-শূন্যই থাকবে। এটিই CRC-কে প্যারিটির চেয়ে বাস্তবে অনেক বেশি নির্ভরযোগ্য করে তোলে।

অনুশীলন

  1. পরীক্ষা করুন: উপরের কোড সেলে flip_index-এর মান বদলে অন্য একটি বিট পজিশন বেছে নিন — নিশ্চিত করুন crc_check তারপরও সঠিকভাবে False রিটার্ন করে।

    হ্যাঁ, যেকোনো একক পজিশনের বিট ফ্লিপ করলে crc_check False রিটার্ন করবে (নির্দিষ্ট কিছু বিরল ব্যতিক্রম বাদে, যা এই ছোট উদাহরণে ঘটে না) — কারণ mod2_divide প্রতিটি বার নতুন করে সম্পূর্ণ বার্তার উপর প্রকৃত XOR ডিভিশন চালায়, কোনো হার্ডকোডেড ফলাফল নেই।

  2. চিন্তা করুন: generator-এর দৈর্ঘ্য বাড়ালে (যেমন একটি দীর্ঘতর জেনারেটর পলিনোমিয়াল ব্যবহার করলে) চেক বিটের সংখ্যা কীভাবে বদলাবে?

    চেক বিটের সংখ্যা সবসময় len(generator_bits) - 1 — তাই দীর্ঘতর জেনারেটর ব্যবহার করলে বেশি চেক বিট যুক্ত হবে (ওভারহেড বাড়বে), কিন্তু সাধারণত এরর-ডিটেকশন ক্ষমতাও বাড়ে (আরও বেশি এরর-প্যাটার্ন ধরতে পারে) — এটিই CRC ডিজাইনে ওভারহেড বনাম নির্ভরযোগ্যতার একটি ট্রেড-অফ, যা বাস্তব প্রোটোকল ডিজাইনাররা সাবধানে বেছে নেন (যেমন CRC-32 ৩২-বিট চেক ব্যবহার করে)।

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

আগের পাঠ
ফ্রেমিং ও ডেটা লিংক লেয়ার বেসিকস