Рубріки: Основи

Сокети в Python. Мережеве програмування та модуль socket

Дмитро Сімагін

Сокети – це фундаментальна концепція для забезпечення зв’язку між пристроями чи процесами через мережу. Завдяки сокетам програми можуть обмінюватися даними через різні мережеві протоколи. Сьогодні ми ознайомимось з основами сокетів і навчимося створювати прості серверні та клієнтські програми на Python.

Що таке сокет?

Сокет — це кінцева точка в двосторонньому зв’язку між пристроями, свого роду телефон, на який дзвонить абонент. Він діє як міст для мережевої комунікації. Застосування сокетів можна описати ось так:

  • Додаток генерує сокет, який підключається до іншого сокету (зазвичай на іншому пристрої).
  • Далі відбувається обмін даними між обома сокетами.
  • Завершивши сеанс зв’язку, сокет закривається.

Робота з сокетами в Python здійснюється за допомогою вбудованої бібліотеки, яка підтримує обидва типи з’єднань: TCP та UDP.

Типи протоколів

У програмуванні сокетів використовуються два різновиди протоколів:

  • TCP — протокол з попереднім встановленням з’єднання, що здійснює повторний запит даних у разі втрати. Часто використовується для надсилання файлів або перегляду веб-сторінок.
  • UDP – протокол без попереднього встановлення з’єднання. Він працює швидше і ефективніше за TCP, але менш надійний. Найчастіше його застосовують у стрімінгу та онлайн-іграх.

Як працювати з сокетами

1. Створення сокету

Для створення сокету вам потрібна функція 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.

2. Як підключити клієнт до сервера

Процес підключення клієнта до сервера відбувається завдяки методу connect(), який передає IP-адресу та номер серверного порту.

# Підключаємось до сервера через IP та порт
s.connect(('localhost', 01234))

 

3. Передача даних

Встановивши стійке з’єднання, можна передавати дані з використанням методу send() і отримувати їх, використовуючи метод recv().

# Передача даних
s.send(b'Welcome, home!')

# Прийом даних
data = s.recv(1024)
print('Received:', data.decode())

 

У методі recv() параметр представляє максимальний обсяг інформації, який може бути прийнятий одночасно (у байтах).

4. Закриття з’єднання

Завершивши сеанс обміну даними, сокет слід закрити з використанням методу close().

# Закриття з'єднання
s.close()

 

Простий приклад TCP-клієнта та сервера

Тепер нам потрібно створити базовий приклад взаємодії 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()

 

Робота з сокетами UDP

На відміну від 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

Використовуючи сокетами, ви зможете створювати широкий перелік мережевих програм, включаючи веб-сервери, чати, стрімінгові сервіси та ігри. Вони підходять майже скрізь, де потрібний мережевий обмін даними. Але як і в будь-якій технології, сокети мають переваги та деякі обмеження. Почнемо з переваг.

Переваги сокетів

  1. Гнучкість у розробці. Оскільки сокети надають низькорівневий доступ до мережевих з’єднань, це дає розробникам можливість створювати різні види мережевих програм, починаючи від простих серверів до складних розподілених систем. Іншими словами, ви маєте повну свободу у розробці мережевої архітектури та протоколів передачі даних.
  2. Підтримка різноманітних протоколів. Сокети підтримують роботу з кількома мережевими протоколами, включаючи TCP та UDP. Це дозволяє створювати програми з різними вимогами до швидкості передачі даних та надійності з’єднання.
  3. Бібліотека socket входить до стандартного набору бібліотек Python, тому вам не потрібно встановлювати додаткові модулі. Це не тільки полегшує роботу, але і робить ваш код більш лаконічним.
  4. Підтримка багатозадачності та багатопоточності. Python дозволяє створювати багатопотокові та асинхронні програми, що особливо корисно для серверів, де потрібно одночасно обробляти безліч клієнтів.
  5. Кросплатформність. Код Python з використанням сокетів можна запускати як на Windows, так і Linux або macOS. Тобто ваш додаток зможе працювати на різних платформах без особливих змін у коді.

Недоліки сокетів

  1. Складність у розробці та налагодженні. Мережеве програмування досить складне для програмістів-початківців. Потрібно вивчити обробку помилок, тайм-аути, втрату пакетів, паралелізм та синхронізацію. Помилки в мережевому коді можуть стати причиною досить складних багів, а це ускладнює налагодження.
  2. Необхідність ручного керування потоками. Сокети потребують ручного управління передачею даних. Розробнику доведеться самому обробляти фрагментацію та складання пакетів, керувати станом з’єднання та запобігати розривам зв’язку.
  3. Лімітована продуктивність при високому навантаженні. Якщо сервер дуже завантажений запитами, то використання сокетів у Python може бути не дуже ефективним порівняно з такими мовами, як C або C++.
  4. Немає вбудованої підтримки безпеки. Сокети не мають вбудованих засобів для шифрування даних. Тому, щоб забезпечити безпеку передачі даних через SSL/TLS, знадобляться додаткові бібліотеки, такі як ssl Python.

Висновок

Використання сокетів у Python дає розробникам широкі можливості для розробки мережевих програм, забезпечуючи гнучкість та контроль над з’єднаннями. Але робота з ними потребує глибокого розуміння мережевих принципів та обліку різних чинників, які можуть впливати на продуктивність і надійність. Вибір на користь сокетів залежить від конкретних вимог програми: для низькорівневого контролю вони підходять ідеально, але більш високорівневих завдань можуть знадобитися додаткові бібліотеки і фреймворки.

 

Останні статті

Більше 8 млрд грн податків. Стільки сплатили резиденти Дія.City в І кварталі 2025 року

Резиденти Дія.City сплатили до бюджету понад 8 млрд грн податків в І кварталі 2025 року.…

18.04.2025

Китайських офісних працівників закликають менше працювати. Це має допомогти місцевій економіці

У Китаї закликають офісних працівників не працювати надто багато — держава сподівається, що вільний час…

18.04.2025

ChatGPT значно покращив пошук місць по фото. Це посилює проблеми конфіденційності

Експерти звертають увагу на тривожну тенденцію: люди все частіше використовують ChatGPT, щоб визначити місцезнаходження, зображене…

18.04.2025

Середовище розробки IntelliJ IDEA оновлено до версії 2025.1

Компанія JetBrains випустила нову версію мультимовного середовища розробки IntelliJ IDEA 2025.1. Оновлена IDE отримала численні…

18.04.2025

Discord впроваджує функцію сканування обличчя для перевірки віку користувачів

Платформа обміну миттєвими повідомленнями Discord впроваджує функцію перевірки віку за допомогою сканування обличчя. Зараз вона…

18.04.2025

Wikipedia випустила спеціальний датасет, щоб відволікти увагу ботів

Wikipedia намагається захистити себе від тисяч різноманітних ботів-скрейперів, які сканують дані цієї платформи для навчання…

18.04.2025