03.20 Ведение совместного проекта
HTTP-сервер для бедных:
python3 -m http.server
Посмотреть на http://localhost:8000
- Простой способ узнать IP, если работает DNS:
Если DNS не работает или hostname == "localhost":
Пояснение: .connect() для UDP-сокета настраивает поле адрес_отправителя:порт_отправителя, но собственно соединения не устанавливает. адрес_отправителя при этом определяется маршрутизацией — это IP того интерфейса, через который пойдёт передача.
HTTP-сервер, который выводит IP адрес, а не 0.0.0.0
Изучить Модуль http.server
Подсказка: нужна только функция test()
Написать простой http-сервер httpsrv.py порт, который:
- Принимает единственный параметр — порт
При старте вместо http://0.0.0.0:8000/ выводит IP (чтобы поделиться с товарищами)
- Подсказки:
BaseHTTPRequestHandler не достаточно, нужен SimpleHTTPRequestHandler
host, port = "0.0.0.0", порт
ServerClass.address_family можно не трогать
- Проверить, работает ли: скачать файл из каталога
Групповая разработка: precious source + committer
- Разбиться на пары
- В каждой паре, каждому участнику:
- Начать «разработку проекта»
- Сделать пустой precious source репозиторий
- Настроить репозиторий для публикации:
При каждом обновлении репозитория будет запускаться git update-server-info (это нужно для того, чтобы работала публикация с помощью примитивного сервера)
- Сделать стартовый коммит в него
Опубликовать этот репозиторий (порт 8000) с помощью httpsrv.py
$ cd .git $ python3 httpsrv.py 8000
Напоминание: сам репозиторий лежит в каталоге .git
- Участвовать в разработке другого проекта
- Склонировать опубликованный precious source репозиторий партнёра:
$ git clone http://адрес/порт какое-то_название
Настроить получившийся committer-репозиторий для публикации (с помощью того же хука post-update)
- Сделать в нём пару коммитов
- Сделать в нём аннотированный тег
$ git tag название_тега -a -m "Аннотация тега"
Опубликовать этот репозиторий (порт 8001) с помощью httpsrv.py
- Склонировать опубликованный precious source репозиторий партнёра:
- Принять запрос на слияние:
- Добавить опубликованный committer-репозиторий партнёра в качестве ещё одного remote:
Помержиться с тегом название_тега
$ git merge название_тега
- Начать «разработку проекта»
TODO будет ли время? Групповая разработка: merge request в gitlab
- Разминка перед многопользовательским MUD
Заставляем работать Тупой netcat и Чат сервер из позапрошлой лекции
По аналогии с примером командной строки, в которую время от времени спамит второй поток вычислений, написать более удобный клиент к общему чату:
- В командной строке должны поддерживаться две команды:
hi — шлёт сообщение "Hello everybody" (с помощью .sendall())
say сообщение — шлёт сообщение (с помощью .sendall())
Приём сообщений делать в отдельном треде (с помощью .recv(1024))
- В командной строке должны поддерживаться две команды:
Д/З
Задача_1. Многопользовательский MUD (multiuser multiuser dungeon)
Скопируйте решение Задачи_1 с предыдущего занятия. Сделайте коммит. Работайте на ветке work.
- Сделайте (наконец-то!) MUD многопользовательским. Подробности ниже.
- Многосессионность (поддержку работы с одним сервером одновременно нескольких клиентов) реализуйте по схеме "коровьего чата" из лекций.
- Именованные сеансы:
При подключении клиента к серверу, клиент передаёт серверу имя пользователя (строка без пробелов, поступает клиенту при запуске - python mymud.py username).
- Сервер проверяет, что подключенного пользователя с таким именем ещё нет; если есть - отказывает в подключении; если нет, то создает подключение (сообщая об этом клиенту) и запоминает имя пользователя.
- Асинхронность работы клиента с сервером:
- после отправки сообщения серверу, клиент НЕ ждёт ответа от сервера
- все сообщения от сервера клиенту _после_ успешного подключения - "асинхронные", т.е. принимаются параллельно работе пользователя с командной строкой
- все сообщения от сервера клиенту предназначены ДЛЯ ВЫВОДА "as is", никакого разбора в духе "набор параметров от сервера к клиенту" теперь не нужно; т.е. клиент отправляет команды на сервер без ожидания ответа и без "понимания", что сообщения от сервера приходят в ответ на конкретные команды
схема параллельного ожидания сообщений и обработки пользовательского ввода - см. лекцию (раздел "Cmd и асинхронные сообщения")
- важно: после получения от сервера (и вывода) сообщения, клиент должен показать командную строку с набранным (но не введённым) пользователем текстом, чтобы результат ввода не исчезал (опять см. лекцию)
- Частичная неделимость обработки пользовательской команды на сервере (для ограничения гонок):
- помним, что сервер последовательный
- получив команду от клиента, сервер обрабатывает её сразу (а не планирует обработку через async)
- отправку сообщения клиенту (клиентам) сервер осуществляет асинхронно
- Широковещательные сообщения от сервера клиентам:
- сообщения о "знаковых событиях" сервер рассылает всем клиентам, в духе коровьего чата (где он транслирует всем клиентам полученное от клиента сообщение)
- знаковые события:
- атака на монстра (сообщать: кто атаковал (имя пользователя), чем, какого монстра, сколько очков здоровья снёс, сколько о.з. осталось; если монстр убит, то сообщить об этом [чтобы клиентам не пришлось выпарсивать число о.з.]) сколько включая результат)
- установка монстра (кто поставил, имя монстра, кол-во о.з.)
- заход пользователя (в т.ч. сообщить имя) в MUD
- прекращения сеанса пользователя в MUD (тоже с указанием имени)
- есть и не-широковещательные сообщения, например приветствие от встреченного монстра поступает одному конкретному пользователю
- Прямого взаимодействия между пользователями нет
- Возможны логические гонки: например, два пользователя более-менее одновременно отправили команду атаки на одного и того же монстра, "первый" убил монстра, а второму пришло индивидуальное сообщение о том, что монстра нет. Это терпимо.