# IP multicast Один контейнер принимает UDP-датаграммы на порту 9999 и пересылает их на multicast-адрес `224.0.2.0:10000`. Три контейнера-получателя присоединяются к этой группе и печатают полученные сообщения. В примере нет подтверждений, повторной передачи и восстановления пропусков. ## Запуск Из корня репозитория перейдите в каталог примера и запустите контейнеры: ```sh cd materials/04-group-comm/seminar/ip_multicast docker compose up --build -d docker compose logs -f sender receiver1 receiver2 receiver3 ``` Дождитесь сообщения `ready` от отправителя и каждого получателя. Последняя команда показывает журналы и занимает терминал. Следующие команды выполняйте во втором терминале из того же каталога. Отправьте пробное сообщение через Python 3: ```sh python -c "import socket; s=socket.socket(socket.AF_INET,socket.SOCK_DGRAM); s.sendto(b'probe',('127.0.0.1',9999)); s.close()" ``` При необходимости замените `python` на имя Python 3 в своём окружении. Убедитесь, что `probe` появился в журналах всех трёх получателей. Отправитель также печатает каждую пересылку. Имена сервисов в журнале позволяют различить получателей. Если с хоста сообщения не доходят (нет `forwarded`), отправляйте из контейнера: `docker compose exec sender python -c "..."`. ## Эксперимент: получатель пропустил сообщение До запуска предположите, какие получатели увидят `m1` и `m2` и получит ли вернувшийся участник пропущенные данные. 1. Остановите третьего получателя: ```sh docker compose stop receiver3 ``` 2. Отправьте `m1`: ```sh python -c "import socket; s=socket.socket(socket.AF_INET,socket.SOCK_DGRAM); s.sendto(b'm1',('127.0.0.1',9999)); s.close()" ``` 3. Верните третьего получателя: ```sh docker compose start receiver3 ``` 4. Дождитесь **нового** сообщения `ready` от `receiver3` и снова отправьте `probe`. Убедитесь, что третий получатель его видит. 5. Отправьте `m2`, заменив в команде `b'm1'` на `b'm2'`. При штатной работе стенда `m1` увидят первый и второй получатели, а `m2` — все три. Третий получатель не получит `m1` задним числом: программа не хранит историю и не запрашивает пропущенные сообщения. UDP допускает потери и без отключения получателя; успешная проба не является доказательством гарантированной доставки. Обсудите: - Какие действия выполняет `IP_ADD_MEMBERSHIP` и где задаётся адрес группы? - Где в программе можно было бы добавить подтверждения или восстановление пропусков? - Почему получение сетевого пакета и надёжная доставка сообщения приложению — разные события? Пустая UDP-датаграмма тоже является сообщением: `b''` не означает закрытие соединения. Можно отправить её и затем обычное сообщение, чтобы проверить, что оба процесса продолжают работу. Повторный запуск контейнера в этом эксперименте иллюстрирует пропуск данных. В домашнем задании используется модель crash-stop: отказавшие процессы не возвращаются. ## Завершение Остановите просмотр журналов сочетанием Ctrl+C, затем удалите контейнеры стенда: ```sh docker compose down ```