Мережеві сокети (Network Sockets): фундамент інтернету 🌐 | Глибоке занурення
У попередній статті ми говорили про WebSockets — технологію, що дозволяє створювати інтерактивні чати в браузері. Але WebSocket — це лише верхівка айсберга. Під капотом браузера, веб-сервера чи будь-якої мережевої програми працює фундаментальний механізм операційної системи — мережевий сокет.
Якщо ви коли-небудь налаштовували Nginx і бачили помилку “Address already in use“, або дивувалися, що таке файл .sock у Linux — ця стаття для вас. Сьогодні ми спустимося на рівень нижче і розберемося, як комп’ютери насправді спілкуються між собою.
Що таке сокет в операційній системі?
У найпростішому розумінні, мережевий сокет (Network Socket) — це програмна кінцева точка (endpoint) для прийому або відправки даних у комп’ютерній мережі. Це абстракція, яку операційна система надає програмам, щоб ті могли сказати: “Я хочу відправити дані туди” або “Я хочу слухати дані звідси“.
Щоб створити з’єднання через інтернет, сокет повинен мати унікальну адресу, яка складається з двох частин:
- IP-адреса: Адреса комп’ютера в мережі (наприклад,
192.168.1.1). - Порт: Числовий ідентифікатор конкретної програми на цьому комп’ютері (наприклад,
80для веб-сервера).
Я люблю використовувати аналогію з багатоквартирним будинком:
- IP-адреса — це адреса самого будинку (вулиця, номер). Листоноша знає, куди нести листа.
- Порт — це номер квартири. Без нього лист дійде до будинку, але не знайде конкретного отримувача.
- Сокет — це двері в квартиру. Саме через них мешканець (програма) отримує та передає “посилки” (дані).
Два головні гравці: TCP vs UDP
Коли ви створюєте сокет, ви повинні обрати “правила спілкування”, тобто протокол транспортного рівня. Їх два, і вони кардинально різні.
| Характеристика | TCP (Transmission Control Protocol) | UDP (User Datagram Protocol) |
|---|---|---|
| Головна фішка | Надійність. Гарантує доставку. | Швидкість. “Вистрілив і забув”. |
| З’єднання | Встановлює стійкий канал (Handshake, “рукостискання”). | Без встановлення з’єднання. |
| Порядок даних | Гарантує правильний порядок пакетів (1, 2, 3…). | Пакети можуть приходити вроздріб або губитися. |
| Де використовується | Веб-сайти (HTTP), пошта, файли, WebSockets. | Відеострімінг, онлайн-ігри (FPS), DNS. |
Цікавий факт: Весь інтернет, який ми звикли бачити (сайти, API), побудований на TCP-сокетах, тому що нам важливо, щоб сторінка завантажилася повністю, без втрачених шматків.
Окремий вид мистецтва: Unix Domain Sockets
Якщо ви налаштовували зв’язку Nginx + PHP-FPM, ви могли бачити такий рядок у конфігурації: fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;.
Що це за файл .sock? Це Unix-сокет. Він використовується для спілкування програм всередині одного комп’ютера.
- Швидкість: Це набагато швидше за звичайні TCP-сокети (навіть на
127.0.0.1), тому що ядру ОС не потрібно загортати дані в мережеві пакети, рахувати контрольні суми і ганяти їх через мережевий стек. - Безпека: Оскільки це файл, ви можете налаштувати права доступу (
chmod/chown) так, щоб тільки Nginx міг “писати” в сокет PHP.
Практика: “слухаємо” порт на Python
Щоб відчути, як це працює, давайте створимо найпростіший TCP-сервер на Python. Він буде використовувати низькорівневу бібліотеку socket, яка є прямим інтерфейсом до системних викликів ОС.
Код сервера (server.py)
import socket
# Створюємо TCP/IP сокет
# AF_INET = IPv4
# SOCK_STREAM = TCP
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Прив'язуємо сокет до адреси та порту
# localhost означає, що сервер доступний тільки на цьому комп'ютері
server_address = ('localhost', 10000)
print(f'Запуск сервера на {server_address[0]} порт {server_address[1]}')
server_socket.bind(server_address)
# Починаємо слухати (чекаємо на вхідні дзвінки)
server_socket.listen(1)
while True:
print('Чекаю на з\'єднання...')
# accept() блокує виконання, поки хтось не підключиться
# connection - це НОВИЙ сокет спеціально для цього клієнта
connection, client_address = server_socket.accept()
try:
print(f'Підключився клієнт: {client_address}')
while True:
# Отримуємо дані (по 16 байт)
data = connection.recv(16)
if data:
print(f'Отримано: {data.decode()}')
# Відправляємо дані назад (Ехо-сервер)
connection.sendall(data)
else:
print(f'Більше немає даних від {client_address}')
break
finally:
# Обов'язково закриваємо з'єднання ("кладемо слухавку")
connection.close()
Коли ви запустите цей код, ваша ОС відкриє порт 10000 і буде чекати. Ви можете підключитися до нього навіть через браузер (хоча він не зрозуміє відповіді) або через команду telnet localhost 10000.
Висновок: все є файлом (або сокетом)
У світі Unix/Linux є приказка: “Все є файлом”. Мережевий сокет — це найкраща ілюстрація цього принципу. Для програми це просто дескриптор, у який можна писати і з якого можна читати, а операційна система бере на себе всю магію доставки цих байтів на інший кінець світу.
Розуміння різниці між TCP, UDP та Unix-сокетами дозволяє вам приймати правильні архітектурні рішення. Наприклад, вибирати Unix-сокети для локального з’єднання бази даних або розуміти, чому для відеодзвінків краще підходить UDP. Це база, на якій стоїть вся ваша веб-розробка.