TCP/IP vs UDP

যেকোনো স্কেলেবল সিস্টেম (যেমন: ডিস্ট্রিবিউটেড সিস্টেম, রিয়েল-টাইম অ্যাপ, গেমিং সার্ভার বা ফাইল ট্রান্সফার সার্ভিস) ডিজাইন করার সময় কমিউনিকেশন প্রোটোকল (Communication Protocol) বেছে নেওয়াটা অত্যন্ত গুরুত্বপূর্ণ একটি ধাপ। নেটওয়ার্কিংয়ের দুনিয়ায় ডেটা ট্রান্সফারের জন্য মূলত দুটি প্রোটোকল সবচেয়ে বেশি ব্যবহৃত হয়—TCP/IP এবং UDP।

কোন প্রোটোকলটি তোমার প্রজেক্টের জন্য সেরা হবে, তা নির্ভর করে তোমার সিস্টেমের রিকোয়ারমেন্টের ওপর—তুমি কি ডেটার শতভাগ নিশ্চয়তা (Reliability) চাও, নাকি দ্রুতগতি (Speed)? চলো, বিষয়গুলো আরও গভীরভাবে বিশ্লেষণ করি।

TCP (Transmission Control Protocol): রিলায়্যাবল কমিউনিকেশন

TCP হলো একটি Connection-oriented প্রোটোকল। এর মানে হলো, সেন্ডার (Sender) এবং রিসিভারের (Receiver) মধ্যে ডেটা আদান-প্রদান শুরু হওয়ার আগে একটি ডেডিকেটেড কানেকশন তৈরি হয়।

Deep Dive: 3-Way Handshake TCP কানেকশন তৈরি করার জন্য 3-Way Handshake মেকানিজম ব্যবহার করে:

১. SYN: ক্লায়েন্ট সার্ভারকে কানেক্ট করার রিকোয়েস্ট পাঠায়।

২. SYN-ACK: সার্ভার সেই রিকোয়েস্ট গ্রহণ করে একটি অ্যাকনলেজমেন্ট (Acknowledgement) পাঠায়।

৩. ACK: ক্লায়েন্ট আবার কনফার্ম করে এবং এরপরই ডেটা ট্রান্সফার শুরু হয়।

TCP এর গুরুত্বপূর্ণ বৈশিষ্ট্য:

  • Reliable (নির্ভরযোগ্য): পথে কোনো ডেটা প্যাকেট হারিয়ে গেলে TCP নিজে থেকে সেটি আবার সেন্ড (Resend) করে।

  • Ordered (সুশৃঙ্খল): তুমি যে অর্ডারে ডেটা পাঠাবে, রিসিভার ঠিক সেই অর্ডারেই ডেটা পাবে। প্যাকেট এলোমেলো হয়ে গেলে রিসিভার সাইডে TCP সেটি সাজিয়ে নেয়।

  • Error Checking: এটি অত্যন্ত কড়াকড়িভাবে ডেটার ইন্টিগ্রিটি (Integrity) চেক করে।

  • Flow & Congestion Control: রিসিভারের প্রসেসিং ক্ষমতার চেয়ে বেশি ডেটা পাঠায় না এবং নেটওয়ার্কে ট্রাফিক বেশি থাকলে ডেটা পাঠানোর স্পিড অটোমেটিক কমিয়ে দেয়।

সিস্টেম ডিজাইনে এর প্রভাব ও ব্যবহার: যেখানে ডেটা হারানো একেবারেই অগ্রহণযোগ্য (Unacceptable), সেখানে TCP হলো বেস্ট চয়েস। যেমন: ব্যাংকিং অ্যাপ, ফাইল ট্রান্সফার (FTP), ইমেইল (SMTP), ওয়েব ব্রাউজিং (HTTP/HTTPS) এবং ডেটাবেস কানেকশন।

UDP (User Datagram Protocol): স্পিড ওভার রিলায়্যাবিলিটি

UDP হলো একটি Connectionless প্রোটোকল। অর্থাৎ, এখানে সেন্ডার এবং রিসিভারের মধ্যে কোনো হ্যান্ডশেক (Handshake) বা পূর্ব-কানেকশন তৈরি হয় না। সেন্ডারের কাজ শুধু ডেটা ফায়ার (Fire) করা, রিসিভার সেটি পেলো কি পেলো না, তা নিয়ে এর কোনো মাথাব্যথা নেই।

Deep Dive: Lightweight Header TCP-এর হেডারের সাইজ হয় ২০ বাইট, যেখানে অনেক ধরনের কন্ট্রোল ইনফরমেশন থাকে। কিন্তু UDP-এর হেডার মাত্র ৮ বাইটের! এতে কোনো সিকোয়েন্স নম্বর বা অ্যাকনলেজমেন্ট লজিক থাকে না। তাই এটি অত্যন্ত হালকা এবং ফাস্ট।

UDP-এর গুরুত্বপূর্ণ বৈশিষ্ট্য:

  • Unreliable (অনিশ্চিত): প্যাকেট হারিয়ে গেলে UDP তার কোনো খোঁজ নেয় না বা রি-সেন্ড করে না।

  • No Ordering: ডেটা এলোমেলো অর্ডারে পৌঁছাতে পারে।

  • Lightning Fast: যেহেতু কোনো থ্রি-ওয়ে হ্যান্ডশেক বা এরর চেকিং নেই, তাই এটি সুপার ফাস্ট।

  • No Congestion Control: নেটওয়ার্কের অবস্থা যেমনই হোক, তুমি যত খুশি ডেটা পাঠাতে পারবে।

সিস্টেম ডিজাইনে এর প্রভাব ও ব্যবহার: যেখানে স্পিড সবচেয়ে বেশি দরকার এবং সামান্য ডেটা লস (Data loss) হলে ইউজারের এক্সপেরিয়েন্সে খুব একটা প্রভাব পড়বে না, সেখানে UDP আদর্শ। যেমন: অনলাইন মাল্টিপ্লেয়ার গেমিং (যেখানে ২ সেকেন্ড আগের ডেটা রি-সেন্ড করার কোনো অর্থ নেই), লাইভ ভিডিও স্ট্রিমিং, এবং VoIP (যেমন: WhatsApp বা Messenger কলিং)।

মডার্ন সিস্টেম ডিজাইন: QUIC প্রোটোকল (HTTP/3)

তোমার ডিজাইনের জ্ঞানে আরও একটি অ্যাডভান্সড বিষয় যুক্ত করা প্রয়োজন। বর্তমানে গুগল (Google) একটি নতুন প্রোটোকল ডেভেলপ করেছে, যার নাম QUIC (Quick UDP Internet Connections)। এটি মূলত UDP-এর ওপর ভিত্তি করে তৈরি, কিন্তু এটি TCP-এর মতো রিলায়েবিলিটি প্রদান করে। মডার্ন HTTP/3 প্রোটোকল মূলত এই QUIC-এর ওপরই চলে, যা একই সাথে স্পিড এবং রিলায়েবিলিটি—দুটোই নিশ্চিত করে।

Example: TCP vs UDP Sockets

কোডের স্ট্রাকচার দেখলেই তুমি বুঝতে পারবে TCP-তে কানেকশন তৈরি করতে হয়, কিন্তু UDP-তে সরাসরি ডেটা রিসিভ করা যায়।

1. TCP Server Example (Connection-oriented)

import socket

# Creating a TCP Socket
tcp_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcp_server.bind(('localhost', 8080))

# TCP requires listening and accepting connections
tcp_server.listen(1)
print("TCP Server is waiting for a connection...")

# Blocking call until a client connects
connection, address = tcp_server.accept()
print(f"Connected securely to: {address}")

# Receiving data
data = connection.recv(1024)
print(f"TCP Received: {data.decode('utf-8')}")

connection.close()

2. UDP Server Example (Connectionless)

import socket

# Creating a UDP Socket
udp_server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
udp_server.bind(('localhost', 9090))

print("UDP Server is active and waiting for packets...")

# No listen() or accept() needed! Direct data reception.
data, client_address = udp_server.recvfrom(1024)

print(f"UDP Received raw packet from {client_address}: {data.decode('utf-8')}")

পরিশেষে মনে রাখার টিপস

  • TCP = Phone Call: আগে রিং হবে, কল রিসিভ হবে (কানেকশন তৈরি), তারপর কথা বলা শুরু হবে। কেউ কথা না বুঝলে তুমি পুনরায় বলবে (Resend)।

  • UDP = Radio Broadcast: রেডিও স্টেশন থেকে সরাসরি সম্প্রচার হচ্ছে। কেউ রেডিও অন করে শুনছে কি না, তা নিয়ে স্টেশনের কোনো মাথাব্যথা নেই, কিন্তু সম্প্রচার খুব দ্রুত ছড়িয়ে পড়ছে।

তুমি যদি তোমার সিস্টেম ডিজাইনে এই কনসেপ্টগুলো পরিষ্কারভাবে বুঝতে পারো, তবে স্কেলেবিলিটি, পারফরম্যান্স এবং রিলায়েবিলিটির ব্যালেন্স করা তোমার জন্য অনেক সহজ হয়ে যাবে।