Модуль socket

Відкрита

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

Давайте копнемо ще глибше. Спочатку ми навчилися працювати з request, потім з http.client, потім з проксі. Що ж далі? А далі ми зазирнемо всім цим бібліотекам під капот…

Сокет (дослівно — розетка) — це точка в мережі, через яку дані відправляються і приймаються. Сокет можна уявити як кінцеву точку двостороннього каналу зв'язку між двома програмами, які працюють на одній або різних машинах.

Сокети підтримують різні мережеві протоколи, але найчастіше використовуються два:

  • TCP (Transmission Control Protocol): Надійний протокол, який забезпечує встановлення з'єднання, перевірку цілісності даних і їх правильну послідовність.
  • UDP (User Datagram Protocol): Протокол, не орієнтований на з'єднання, який не гарантує доставку даних, але є більш швидким та ефективним для певних типів застосунків.

Для ідентифікації сокета використовуються IP-адреса (ідентифікуючий пристрій у мережі) і порт (ідентифікуючий конкретний додаток або сервіс на пристрої).

Важливо! IP-адреса і порт однозначно ідентифікують програму в мережі. Це як адреса дому та номер квартири. Адреса дому (IP-адреса) — це адреса вашого комп'ютера в мережі, а порт — це номер квартири, який програма використовує для отримання і відправлення повідомлень.

Більш детально про те, що таке IP-адреса і порт, ви можете дізнатися в лекціях, присвячених пристрою мережі.

Основні етапи роботи програми з сокетами:

  1. Створення сокета: Програма створює сокет, вказуючи тип протоколу (TCP або UDP).
  2. Прив'язка до адреси: Сокет прив'язується до IP-адреси і номера порта, щоб бути доступним для з'єднань або відправки/отримання даних.
  3. Прослуховування та встановлення з'єднання (для TCP):
    • Прослуховування: Сокет на стороні сервера переводиться в режим прослуховування, очікуючи вхідних з'єднань.
    • Встановлення з'єднання: Клієнт ініціює з'єднання з сервером. Сервер приймає з'єднання, створюючи новий сокет для взаємодії з клієнтом.
  4. Обмін даними: Дані передаються між клієнтом і сервером. У випадку TCP дані передаються в надійному порядку.
  5. Закриття з'єднання: Після завершення обміну даними з'єднання закривається.

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

  • Гнучкість: Сокети дозволяють додаткам обмінюватися даними незалежно від їх місцезнаходження та платформи.
  • Продуктивність: Сокети забезпечують швидкий та ефективний спосіб передачі даних, особливо у випадку використання UDP.
  • Надійність (у випадку TCP): Протокол TCP забезпечує надійну доставку даних з перевіркою цілісності та відновленням втрачених пакетів.

7.2 Створення сокет-сервера

Робота з сокетами в Python здійснюється за допомогою вбудованого модуля socket, який надає інтерфейс для низькорівневого мережевого програмування.

За допомогою сокетів можна створити socket-сервер — додаток/об'єкт, який отримуватиме запити від клієнтів і відповідатиме їм. А також socket-клієнт — додаток/об'єкт, який буде надсилати запити socket-серверу і отримуватиме від нього відповіді.

Щоб створити socket-сервер, потрібно виконати три дії:

  1. Створити об'єкт socket-сервера.
  2. Прив'язати (bind) його до якоїсь IP і порта.
  3. Увімкнути режим прослуховування (listen) вхідних повідомлень.

Виглядати цей код буде приблизно так:

import socket

# Створення сокета
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# Прив'язка сокета до адреси і порта
server_socket.bind(('localhost', 12345))

# Прослуховування вхідних з'єднань
server_socket.listen(5)
print("Сервер очікує з'єднання...")

Тут socket.AF_INET вказує, що ми використовуємо IPv4 для мережевого протоколу, а socket.SOCK_STREAM означає, що ми використовуємо TCP. Ці параметри найчастіше використовуються для створення мережевих додатків.

Після того, як надійшло вхідне повідомлення, потрібно зробити ще чотири дії:

  1. Встановити (accept) з'єднання з клієнтом.
  2. Отримати (receive) запит (дані) від клієнта.
  3. Надіслати (send) клієнту відповідь — теж якісь дані.
  4. Закрити (close) з'єднання.

Виглядає цей код приблизно так:

# Прийняття нового з'єднання
client_socket, client_address = server_socket.accept()
print(f"З'єднання встановлено з {client_address}")

# Отримання даних від клієнта
data = client_socket.recv(1024)
print(f"Отримано: {data.decode('utf-8')}")

# Відправка даних клієнту
client_socket.sendall(b'Hello, client!')

# Закриття з'єднання з клієнтом
client_socket.close()

Метод sendall() використовується замість send(), тому що він гарантує, що всі дані будуть відправлені. Метод send() може відправити тільки частину даних, якщо буфер заповниться.

Число 1024 у recv(1024) вказує максимальну кількість байтів, яку можна отримати за один раз. Це допомагає контролювати обсяг даних, оброблюваних за одну операцію.

Код останнього прикладу зазвичай виконується в безкінечному циклі — сервер обробляє запит, потім чекає нового, потім його обробляє, і так постійно.

Якщо ви хочете запустити його у себе або просто побачити повний приклад, то наведу його тут:

import socket

# Створення сокета
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# Прив'язка сокета до адреси і порта
server_socket.bind(('localhost', 12345))

# Прослуховування вхідних з'єднань
server_socket.listen(5)
print("Сервер очікує з'єднання...")

while True:
    # Прийняття нового з'єднання
    client_socket, client_address = server_socket.accept()
    print(f"З'єднання встановлено з {client_address}")

    # Отримання даних від клієнта
    data = client_socket.recv(1024)
    print(f"Отримано: {data.decode('utf-8')}")

    # Відправка даних клієнту
    client_socket.sendall(b'Hello, client!')

    # Закриття з'єднання з клієнтом
    client_socket.close()

7.3 Створення сокет-клієнта

Сокет-сервер ми створили, тепер давайте напишемо свій сокет-клієнт, який буде звертатися до сервера і отримувати від нього дані у відповідь.

Для цього потрібно виконати п'ять дій:

  1. Створити об'єкт socket-клієнта.
  2. Встановити з'єднання (connect) з IP-адресою і портом нашого socket-сервера.
  3. Відправити (send) повідомлення на сервер.
  4. Отримати (receive) дані від сервера.
  5. Закрити (close) з'єднання.

Насправді це простіше, ніж здається. Ось як буде виглядати цей код:

import socket

# Створення сокета
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# Встановлення з'єднання з сервером
client_socket.connect(('localhost', 12345))

# Відправка даних на сервер
client_socket.sendall(b'Hello, server!')

# Отримання даних від сервера
data = client_socket.recv(1024)
print(f"Отримано від сервера: {data.decode('utf-8')}")

# Закриття сокета
client_socket.close()

Якщо на тій стороні немає запущеного socket-сервера або з'єднання обірвалося, то виникне виняток типу socket.error. Так що не забувайте обробляти винятки.

На цьому ми сьогодні закінчимо роботу з сокетами.

При будь-якій роботі з мережею у вас знову і знову будуть спливати хости, порти, IP-адреси, встановлення з'єднань, прослуховування запитів і все в тому ж дусі. Тож розуміння того, як це працює глибоко всередині, дуже сильно полегшить вам життя і допоможе об'єднати розрізнені знання в єдину картину.

2
Задача
Модуль 1: Python Core,  13 рівень6 лекція
Недоступна
Створення сокет-сервера
Створення сокет-сервера
2
Задача
Модуль 1: Python Core,  13 рівень6 лекція
Недоступна
Створення сокет-клієнта
Створення сокет-клієнта
Коментарі
  • популярні
  • нові
  • старі
Щоб залишити коментар, потрібно ввійти в систему
Для цієї сторінки немає коментарів.