ویژگی تصویر

کتابخانه socket در پایتون — مرجع کاربردی برای برنامه‌نویسی شبکه

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

ماژول socket در پایتون ابزار پایه‌ای برای ایجاد برنامه‌های شبکه‌ای است. این کتابخانه امکان کار با پروتکل‌های TCP و UDP، مدیریت اتصالات، ارسال و دریافت داده و پیکربندی ویژگی‌های سطح سوکت را فراهم می‌کند. در این مقاله به کاربردها، نکات عملی، مثال‌های واقعی و بهترین شیوه‌ها می‌پردازیم تا شما بتوانید با اطمینان برنامه‌های شبکه‌ای قابل اعتماد بسازید.

مفاهیم پایه‌ای

  • Address Family (مثلاً AF_INET برای IPv4، AF_INET6 برای IPv6)
  • Socket Type (SOCK_STREAM برای TCP، SOCK_DGRAM برای UDP)
  • توابع اصلی: socket(), bind(), listen(), accept(), connect(), send(), recv()
  • مفاهیمی مثل blocking و non-blocking، تایم‌اوت، و گزینه‌های سوکت (مثلاً SO_REUSEADDR)

ایجاد یک سرور TCP ساده

import socket

HOST = '127.0.0.1'
PORT = 65432

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    s.bind((HOST, PORT))
    s.listen()
    print('Listening on', (HOST, PORT))
    conn, addr = s.accept()
    with conn:
        print('Connected by', addr)
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data.upper())

توضیح: این کد یک سرور اکو ساده TCP راه‌اندازی می‌کند که داده‌های دریافتی را بزرگ می‌کند و به فرستنده بازمی‌گرداند. با استفاده از context manager (with) سوکت به‌صورت خودکار بسته می‌شود. گزینه SO_REUSEADDR اجازه می‌دهد سریع‌تر پورت را بعد از بسته شدن مجدداً استفاده کنید. تابع recv تا زمانی که داده دریافت کند یا اتصال بسته شود، بلاک می‌کند؛ بنابراین این سرور تک‌کاربره و بلاک‌کننده است.

کلاینت نمونه برای ارتباط با سرور

import socket

HOST = '127.0.0.1'
PORT = 65432

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.connect((HOST, PORT))
    s.sendall(b'hello world')
    data = s.recv(1024)
    print('Received', repr(data))

توضیح: کلاینت به سرور متصل می‌شود، رشته‌ای بایت‌شده ارسال می‌کند و پاسخ را دریافت کرده و چاپ می‌کند. استفاده از sendall تضمین می‌کند تمام بایت‌های پیام ارسال شوند.

مقایسه TCP و UDP

ویژگیTCP (SOCK_STREAM)UDP (SOCK_DGRAM)
قابلیت اطمینانقابل اعتماد، ترتیبیغیرقابل اعتماد، بدون ترتیب
مناسب برایاپلیکیشن‌هایی که تضمین تحویل لازم دارند (HTTP, SSH)زمان پاسخ سریع و حجم کم سربار (DNS, VoIP)
اتصالحالت‌دار (connection-oriented)بدون اتصال

مثال UDP (بدون اتصال)

import socket

SERVER = ('127.0.0.1', 9999)
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.sendto(b'Ping', SERVER)
data, addr = s.recvfrom(1024)
print('Received from', addr, data)
s.close()

توضیح: در UDP نیازی به connect نیست؛ sendto و recvfrom آدرس فرستنده/گیرنده را مدیریت می‌کنند. UDP مناسب زمانی است که تاخیر کمتر و سربار شبکه کمتر نیاز داشته باشیم، ولی مسئولیت اطمینان از تحویل بر عهده برنامه است.

پردازش همزمان اتصالات — استفاده از selectors

import socket
import selectors

sel = selectors.DefaultSelector()

def accept(sock):
    conn, addr = sock.accept()
    conn.setblocking(False)
    sel.register(conn, selectors.EVENT_READ, read)

def read(conn):
    data = conn.recv(1024)
    if data:
        conn.sendall(data)
    else:
        sel.unregister(conn)
        conn.close()

host, port = '127.0.0.1', 65433
lsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
lsock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
lsock.bind((host, port))
lsock.listen()
lsock.setblocking(False)
sel.register(lsock, selectors.EVENT_READ, accept)

while True:
    events = sel.select()
    for key, mask in events:
        callback = key.data
        callback(key.fileobj)

توضیح: این سرور از ماژول selectors استفاده می‌کند تا چندین اتصال را به‌صورت غیرمسدود و بدون ایجاد ترد/فرآیند مجزا مدیریت کند. سوکت گوش‌دهنده به‌صورت non-blocking تنظیم شده و ایونت‌ها با sel.select بررسی می‌شوند تا در زمان مناسب callback اجرا شود. این روش برای سرورهای مقیاس‌پذیر سبک بسیار مناسب است.

تنظیمات و گزینه‌های مفید

  • SO_REUSEADDR: برای بازنشانی سریع پورت بعد از بسته شدن.
  • SO_KEEPALIVE: ارسال بسته‌های keepalive برای تشخیص قطع ناگهانی.
  • setsockopt(SOL_TCP, TCP_NODELAY, 1): غیرفعال کردن Nagle در حالات با تأخیر کم.
  • settimeout(value): مشخص کردن زمان انتظار برای عملیات بلاک.

نکات امنیتی و عملیاتی

  • هرگز داده‌های ورودی از شبکه را بدون اعتبارسنجی و پاک‌سازی پردازش نکنید.
  • از TLS/SSL برای رمزنگاری ارتباط‌های حساس استفاده کنید (ماژول ssl در پایتون).
  • در محیط تولید از سیستم‌های مدیریت اتصال (مثلاً socketserver یا فریم‌ورک‌های سرتاسر) یا سرویس‌دهنده‌های reverse proxy مانند nginx بهره ببرید.
  • مانیتورینگ و لاگ‌گیری برای تشخیص نشت منابع یا DoS بسیار مهم است.

بهینه‌سازی و خطایابی

برای اشکال‌زدایی، از ابزارهایی مثل tcpdump، Wireshark و strace استفاده کنید تا ترافیک و syscalls را بررسی کنید. در طراحی پروتکل روی اندازه بافرها، مدیریت خطا و بازیافت منابع تمرکز کنید تا از memory leak و sockets in TIME_WAIT جلوگیری شود.

منابع و مسیرهای بعدی

  • مستندات رسمی پایتون برای ماژول socket و ssl
  • مطالعه طراحی پروتکل‌ها (HTTP, WebSocket, gRPC) و کتابخانه‌هایی که سطح بالاتری فراهم می‌کنند
  • بررسی AsyncIO برای برنامه‌های شبکه‌ای غیرهمزمان با API سطح بالا

نتیجه‌گیری: ماژول socket ابزار پایه و قدرتمندی برای کار شبکه در پایتون است. با یادگیری اصول، استفاده از الگوهای مناسب مانند selectors یا asyncio، و رعایت نکات امنیتی، می‌توانید سرور و کلاینت‌های قابل اعتماد و مقیاس‌پذیر بسازید.

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

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