52. (П23) Мультиплексування TCP + UDP в одному selectors-циклі¶
Передумови¶
- Прочитана Лекція 44 — UDP
- Прочитана Лекція 49 — Неблокуючі сокети
- Виконане Практичне 22 (файл 50) — Неблокуючий TCP ехо-сервер — беремо його
echo_server_nb.pyяк основу - Утиліта
nc
Навіщо це практичне
На UDP саме по собі неблокуючий режим виграшу не дає — там нема з'єднань, які б одне одному заважали. Виграш з'являється тоді, коли в одному event-loop живуть сокети різних типів. Цього разу ви додасте UDP-сокет у той самий selectors, що вже обслуговує TCP-ехо з П22, — і побачите, що selectors нічого не змінює: API однаковий для обох транспортів.
Персоналізація
Залиште STUDENT = "Imya Prizvysche" з П22 і виведіть print(f"Student: {STUDENT}") при старті.
Завдання¶
Скопіюйте echo_server_nb.py з П22 у файл echo_server_mux.py і додайте до нього UDP-гілку.
Після ваших змін один процес тримає:
- TCP на
127.0.0.1:9100— поведінка без змін з П22: вітанняHello from <STUDENT>!\n, лічильникn, ехо[<n>] <msg>\n, акуратне закриття наb"". - UDP на
127.0.0.1:9101—SOCK_DGRAM,setblocking(False),bind. На кожну отриману датаграму сервер відправляє назад[udp] <msg>тому ж відправникові (sendto(data, addr)).
Обидва сокети живуть в одному selectors.DefaultSelector і одному циклі sel.select(). Розрізнити їх у обробнику зручно через key.data:
sel.register(server_tcp, selectors.EVENT_READ, data=None) # TCP-listener
sel.register(server_udp, selectors.EVENT_READ, data="udp") # UDP-сокет
# а TCP-клієнти, як і в П22, реєструються з dict у data
У головному циклі:
for key, _mask in sel.select():
if key.data is None:
accept(...) # новий TCP-клієнт
elif key.data == "udp":
handle_udp(key.fileobj) # UDP-датаграма(и)
else:
serve(...) # TCP-клієнт з П22
Тестування. Обидва транспорти живі одночасно¶
Запустіть сервер. У двох окремих терміналах:
Обидва клієнти отримують відповіді в одному й тому ж процесі сервера.
Результат¶
Скріншот з трьох вікон: лог сервера, TCP-клієнт (nc), UDP-клієнт (nc -u). У логу мають бути присутні події обох транспортів і Student: <Ім'я>.
Знайшли помилку чи бажаєте додати інформацію, щоб покращити курс? Створіть issue на GitHub