Сокети в Python. Мережеве програмування та модуль socket
Сокети – це фундаментальна концепція для забезпечення зв’язку між пристроями чи процесами через мережу. Завдяки сокетам програми можуть обмінюватися даними через різні мережеві протоколи. Сьогодні ми ознайомимось з основами сокетів і навчимося створювати прості серверні та клієнтські програми на Python.
Сокет — це кінцева точка в двосторонньому зв’язку між пристроями, свого роду телефон, на який дзвонить абонент. Він діє як міст для мережевої комунікації. Застосування сокетів можна описати ось так:
Робота з сокетами в Python здійснюється за допомогою вбудованої бібліотеки, яка підтримує обидва типи з’єднань: TCP та UDP.
У програмуванні сокетів використовуються два різновиди протоколів:
Для створення сокету вам потрібна функція socket.socket(), яка створює новий об’єкт.
import socket # Створення сокету s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
У цьому прикладі socket.AF_INET визначає адреси IPv4, а socket.SOCK_STREAM вказує тип сокета для TCP.
Якщо ви хочете використовувати UDP, то ви повинні використовувати socket.SOCK_DGRAM.
Процес підключення клієнта до сервера відбувається завдяки методу connect(), який передає IP-адресу та номер серверного порту.
# Підключаємось до сервера через IP та порт s.connect(('localhost', 01234))
Встановивши стійке з’єднання, можна передавати дані з використанням методу send() і отримувати їх, використовуючи метод recv().
# Передача даних s.send(b'Welcome, home!') # Прийом даних data = s.recv(1024) print('Received:', data.decode())
У методі recv() параметр представляє максимальний обсяг інформації, який може бути прийнятий одночасно (у байтах).
Завершивши сеанс обміну даними, сокет слід закрити з використанням методу close().
# Закриття з'єднання s.close()
Тепер нам потрібно створити базовий приклад взаємодії TCP-клієнта з сервером Python.
Код сервера
Сервер прослуховуватиме порт 01234, встановить з’єднання з клієнтами та відповість на їхні запити.
import socket # Створення сокету server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # Прив'язуємо сокет до IP-адреси та порту server_socket.bind(('localhost', 01234)) # Очікування вхідних підключень (максимум 5 клієнтів у черзі) server_socket.listen(5) print('Сервер увімкнено і в режимі очікування...') while True: # Підключення client_socket, addr = server_socket.accept() print('Підключення від:', addr) # Прийом даних data = client_socket.recv(1024) print('Отримано:', data.decode()) # Відправлення повідомлення у відповідь клієнту client_socket.send(b'Hello from server!') # Закриття клієнтського з'єднання client_socket.close()
Код клієнта
Клієнт підключається до сервера через порт 01234, надсилає повідомлення та отримує відповідь.
import socket # Створюємо сокет client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # Підключаємося до сервера client_socket.connect(('localhost', 01234)) # Відправляємо дані client_socket.send(b'Welcome, home!') # Отримуємо відповідь data = client_socket.recv(1024) print('Server response:', data.decode()) # Закриваємо сокет client_socket.close()
На відміну від TCP, сокети UDP не встановлюють з’єднання перед тим, як надіслати дані. Погляньмо на приклади їхньої взаємодії.
Код UDP-сервера
import socket # Створюємо сокет UDP udp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # Прив'язуємо сокет до порту та IP-адреси udp_server_socket.bind(('localhost', 01234)) print('UDP-сервер запущено...') while True: # Отримуємо дані data, addr = udp_server_socket.recvfrom(1024) print('Отримано від:', addr, 'message:', data.decode()) # Відправляємо відповідь udp_server_socket.sendto(b'Привіт від UDP-сервера!', addr)
Код UDP-клієнта
import socket # Створюємо сокет UDP udp_client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # Надсилаємо дані на сервер udp_client_socket.sendto(b'Welcome, home!', ('localhost', 01234)) # Отримуємо відповідь data, addr = udp_client_socket.recvfrom(1024) print('UDP server response:', data.decode()) # Закриваємо сокет udp_client_socket.close()
Програмування сокетів може включати різні помилки, такі як проблеми з підключенням або помилки тайм-ауту. Бібліотека сокетів Python надає кілька винятків: socket.error, socket.timeout та інші для обробки таких ситуацій. Ось приклад обробки помилки підключення:
import socket try: # Створюємо сокет і підключаємося до сервера client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) client_socket.connect(('localhost', 01234)) client_socket.send(b'Welcome, home!') # Отримуємо відповідь data = client_socket.recv(1024) print('Server response:', data.decode()) except socket.error as e: print(f'Socket error: {e}') finally: # Закриваємо сокет client_socket.close()
За замовчуванням сокети блокуються, тобто вони нескінченно чекають на завершення операцій. Однак ви можете встановити сокет в режим, що не блокується, або застосовувати тайм-аути.
Встановлення тайм-ауту
import socket s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.settimeout(5) # Встановити тайм-аут за 5 секунд try: s.connect(('localhost', 01234)) s.send(b'Welcome, home!') data = s.recv(1024) print('Received:', data.decode()) except socket.timeout: print('Connection timed out') finally: s.close()
Використання неблокованого режиму
import socket s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.setblocking(False) # Встановити сокет у неблокуючий режим try: s.connect(('localhost', 01234)) except BlockingIOError: print('Неблокуючий режим: Спроба підключення виконується') s.close()
Використовуючи сокетами, ви зможете створювати широкий перелік мережевих програм, включаючи веб-сервери, чати, стрімінгові сервіси та ігри. Вони підходять майже скрізь, де потрібний мережевий обмін даними. Але як і в будь-якій технології, сокети мають переваги та деякі обмеження. Почнемо з переваг.
Використання сокетів у Python дає розробникам широкі можливості для розробки мережевих програм, забезпечуючи гнучкість та контроль над з’єднаннями. Але робота з ними потребує глибокого розуміння мережевих принципів та обліку різних чинників, які можуть впливати на продуктивність і надійність. Вибір на користь сокетів залежить від конкретних вимог програми: для низькорівневого контролю вони підходять ідеально, але більш високорівневих завдань можуть знадобитися додаткові бібліотеки і фреймворки.
Резиденти Дія.City сплатили до бюджету понад 8 млрд грн податків в І кварталі 2025 року.…
У Китаї закликають офісних працівників не працювати надто багато — держава сподівається, що вільний час…
Експерти звертають увагу на тривожну тенденцію: люди все частіше використовують ChatGPT, щоб визначити місцезнаходження, зображене…
Компанія JetBrains випустила нову версію мультимовного середовища розробки IntelliJ IDEA 2025.1. Оновлена IDE отримала численні…
Платформа обміну миттєвими повідомленнями Discord впроваджує функцію перевірки віку за допомогою сканування обличчя. Зараз вона…
Wikipedia намагається захистити себе від тисяч різноманітних ботів-скрейперів, які сканують дані цієї платформи для навчання…