کتابخانه 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 و فریمورکهای اختصاصی استفاده کنید.
آیا این مطلب برای شما مفید بود ؟





