ویژگی تصویر

کتابخانه socketserver در پایتون — مرجع کاربردی و حرفه‌ای

  /  پایتون   /  کتابخانه socketserver در پایتون
بنر تبلیغاتی الف

کتابخانهٔ استاندارد socketserver در پایتون یک چارچوب سبک برای ساخت سرورهای شبکه‌ای مبتنی بر سوکت است. این کتابخانه با فراهم‌کردن کلاس‌های سرور و هندلر، پیاده‌سازی الگوهای رایج مانند سرور تک‌نخی، چندنخی و چندفرآیندی را ساده می‌کند. در این مقاله به معماری، مثال‌های عملی، نکات بهینه‌سازی و محدودیت‌های این کتابخانه می‌پردازیم.

معماری و اجزای کلیدی

  • BaseRequestHandler: کلاس پایه برای نوشتن منطق پردازش هر درخواست. متدهای مهم: setup(), handle(), finish().
  • TCPServer و UDPServer: پیاده‌سازی‌های پایه برای پروتکل‌های TCP و UDP.
  • StreamRequestHandler: برای کار با کانال‌های مبتنی بر فایل/سوکت که خواندن و نوشتن با روش‌های شبیه فایل مفید است.
  • MixInها: مانند ThreadingMixIn و ForkingMixIn که به سرور قابلیت چندنخی یا چندفرآیندی می‌دهند.

مقایسهٔ سریع کلاس‌های سرور

کلاسمزیتمعایب
TCPServerساده و قابل فهمدرخواست‌ها به صورت متوالی پردازش می‌شوند
ThreadingTCPServerهمزمانی ساده با نخ‌هاهزینهٔ حافظه/ترافیک نخ‌ها، نیاز به همگام‌سازی
ForkingTCPServerجداشدگی بهتر بین درخواست‌هاهزینهٔ بالا در ویندوز، سنگین بودن فرآیندها

مثال پایه — سرور Echo با TCP

from socketserver import TCPServer, StreamRequestHandler

class EchoHandler(StreamRequestHandler):
    def handle(self):
        data = self.rfile.readline().strip()
        self.wfile.write(data + b'n')

if __name__ == '__main__':
    with TCPServer(('0.0.0.0', 9999), EchoHandler) as server:
        server.serve_forever()

این کد یک سرور ساده TCP راه‌اندازی می‌کند که هر خط از ورودی را خوانده و همان را بازمی‌گرداند. کلاس EchoHandler از StreamRequestHandler استفاده می‌کند تا بتوانیم از self.rfile و self.wfile به‌عنوان شیءهای فایل استفاده کنیم. استفاده از with باعث بسته‌شدن خودکار سوکت هنگام پایان می‌شود.

نوشتن یک کلاینت ساده برای تست

import socket

with socket.create_connection(('127.0.0.1', 9999)) as s:
    s.sendall(b'hellon')
    print(s.recv(1024))

کلاینت بالا به سرور متصل شده، رشته‌ای می‌فرستد و پاسخ را دریافت می‌کند. این مثال برای تست سریع سرور Echo مناسب است.

ارتقای سرور به حالت چندنخی

from socketserver import ThreadingMixIn, TCPServer, StreamRequestHandler

class ThreadedTCPServer(ThreadingMixIn, TCPServer):
    daemon_threads = True
    allow_reuse_address = True

class EchoHandler(StreamRequestHandler):
    def handle(self):
        for line in self.rfile:
            self.wfile.write(line)

در این نسخه ThreadingMixIn اضافه شده تا برای هر اتصال یک نخ جدا ایجاد شود. گزینه daemon_threads = True باعث می‌شود نخ‌ها هنگام خروج نرم از پروسه، خاتمه پیدا کنند. allow_reuse_address به جلوگیری از خطای “address already in use” پس از بسته‌شدن سریع کمک می‌کند.

بهترین شیوه‌ها و نکات پیشرفته

  • shutdown() و server_close(): برای خاموش‌کردن امن از thread یا main، از server.shutdown() استفاده کنید که حلقهٔ serve_forever را قطع می‌کند و سپس server.server_close() را فراخوانی کنید.
  • تنظیم timeout: با settimeout یا handle_timeout می‌توانید کنترل بهتری روی فرایندهای بلاک‌شونده داشته باشید.
  • مدیریت استثنا: داخل handle حتماً exceptions را مدیریت کنید تا یک درخواست خطادار، سرور را از کار نیندازد.
  • همگام‌سازی: زمانی که handlerها به منابع مشترک دست می‌زنند از قفل‌ها (Lock) استفاده کنید تا شرایط رقابتی پیش نیاید.

نمونهٔ پیشرفته — خاموش‌سازی نرم و مدیریت استثنا

import threading
from socketserver import ThreadingMixIn, TCPServer, StreamRequestHandler

class ThreadedTCPServer(ThreadingMixIn, TCPServer):
    allow_reuse_address = True
    daemon_threads = True

class SafeEchoHandler(StreamRequestHandler):
    def handle(self):
        try:
            for line in self.rfile:
                self.wfile.write(line)
        except Exception as e:
            # لاگ‌کردن خطا به جای قطع شدن سرور
            print('Handler error:', e)

if __name__ == '__main__':
    server = ThreadedTCPServer(('0.0.0.0', 9999), SafeEchoHandler)
    t = threading.Thread(target=server.serve_forever)
    t.start()
    try:
        # سرور تا زمان Ctrl+C کار خواهد کرد
        t.join()
    except KeyboardInterrupt:
        server.shutdown()
        server.server_close()

در این کد، سرور در یک نخ جدا اجرا می‌شود و هنگام دریافت KeyboardInterrupt با فراخوانی shutdown و server_close به شکلی مرتب بسته می‌شود. داخل handler هم استثناها گرفته شده تا یک خطا باعث از کار افتادن کل فرآیند نشود.

محدودیت‌ها و ملاحظات عملکردی

  • ThreadingMixIn برای برنامه‌هایی با تعداد زیادی اتصال سبک مناسب است، اما برای هزاران اتصال همزمان کارایی کمی دارد—در آن حالت بهتر است سراغ asyncio یا سرورهای مبتنی بر رویداد بروید.
  • ForkingMixIn در سیستم‌عامل‌های یونیکس کاربردی است اما در ویندوز محدودیت دارد.
  • socketserver مناسب پیاده‌سازی پروتکل‌های ساده و ابزارهای داخلی است؛ برای برنامه‌های وب یا پروتکل‌های پیچیده بهتر است از فریم‌ورک‌های تخصصی استفاده کنید.

امنیت و نگهداری

  • هرگز به طور مستقیم داده‌های ورودی را trust نکنید؛ ورودی کاربران را اعتبارسنجی و ضدعفونی کنید.
  • اجازهٔ reuse_address را با آگاهی استفاده کنید؛ گاهی باعث بروز مشکلات امنیتی در برخی پلتفرم‌ها می‌شود.
  • برای ثبت لاگ، از ماژول logging استفاده کنید تا خطاها و دسترسی‌ها را پیگیری کنید.

در نهایت، socketserver یک ابزار مفید و ساده برای سریع پیاده‌سازی سرورهای تست، ابزارهای شبکه‌ای یا سرویس‌های سبک است. با توجه به نیازهای همزمانی، حفظ ثبات و امنیت، می‌توانید از mixinها، timeouts و مدیریت مناسب استثناها بهره ببرید یا در صورت نیاز به عملکرد بالاتر از asyncio و فریم‌ورک‌های اختصاصی استفاده کنید.

آیا این مطلب برای شما مفید بود ؟

خیر
بله
موضوعات شما در انجمن: