Чтение онлайн

на главную - закладки

Жанры

Программирование на языке Ruby
Шрифт:

Давайте напишем скелет шахматного сервера. Мы не имеем в виду программу, которая будет играть в шахматы с клиентом. Нет, наша задача — связать клиентов так, чтобы они могли затем играть без вмешательства сервера.

Предупреждаю, что ради простоты показанная ниже программа ничего не знает о шахматах. Логика игры просто заглушена, чтобы можно было сосредоточиться на сетевых аспектах.

Для установления соединения между клиентом и сервером будем использовать протокол TCP. Можно было бы остановиться и на UDP, но этот протокол ненадежен, и нам пришлось бы использовать тайм-ауты, как в одном из примеров выше.

Клиент может передать два поля: свое имя и имя желательного противника. Для идентификации противника условимся записывать его имя в виде

user:hostname
; мы употребили двоеточие вместо напрашивающегося знака
@
, чтобы не вызывать ассоциаций с электронным адресом, каковым эта строка не является.

Когда от клиента приходит запрос, сервер сохраняет сведения о клиенте у себя в списке. Если поступили запросы от обоих клиентов, сервер посылает каждому из них сообщение; теперь у каждого клиента достаточно информации для установления связи с противником.

Есть еще вопрос о выборе цвета фигур. Оба партнера должны как-то договориться о том, кто каким цветом будет играть. Для простоты предположим, что цвет назначает сервер. Первый обратившийся клиент будет играть белыми (и, стало быть, ходить первым), второй — черными.

Уточним: компьютеры, которые первоначально были клиентами, начиная с этого момента общаются друг с другом напрямую; следовательно, один из них становится сервером. Но на эту семантическую тонкость я не буду обращать внимания.

Поскольку клиенты посылают запросы и ответы попеременно, причем сеанс связи включает много таких обменов, будем пользоваться протоколом TCP. Следовательно, клиент, который на самом деле играет роль «сервера», создает объект

TCPServer
, а клиент на другом конце — объект
TCPSocket
. Будем предполагать, что номер порта для обмена данными заранее известен обоим партнерам (разумеется, У каждого из них свой номер порта).

Мы только что описали простой протокол прикладного уровня. Его можно было бы сделать и более хитроумным.

Сначала рассмотрим код сервера (листинг 18.1). Чтобы его было проще запускать из командной строки, создадим поток, который завершит сервер при нажатии клавиши Enter. Сервер многопоточный — он может одновременно обслуживать нескольких клиентов. Данные о пользователях защищены мьютексом, ведь теоретически несколько потоков могут одновременно попытаться добавить новую запись в список.

Листинг 18.1. Шахматный сервер

require "thread"

require "socket"

PORT = 12000

HOST = "96.97.98.99" # Заменить этот IP-адрес.

# Выход при нажатии клавиши Enter.

waiter = Thread.new do

 puts "Нажмите Enter для завершения сервера."

 gets

 exit

end

$mutex = Mutex.new

$list = {}

def match?(p1, p2)

 return false if !$list[p1] or !$list[p2]

 if ($list[p1][0] == p2 and $list[p2][0] == p1)

true

 else

false

 end

end

def handle_client(sess, msg, addr, port, ipname)

 $mutex.synchronize do

cmd, player1, player2 = msg.split

# Примечание: от клиента мы получаем данные в виде user:hostname,

# но храним их в виде user:address.

p1short = player1.dup # Короткие имена

p2short = player2.split(":")[0] # (то есть не ":address").

player1 << ":#{addr}" # Добавить IP-адрес клиента.

user2, host2 = player2.split(":")

host2 = ipname if host2 == nil

player2 = user2 + ":" + IPSocket.getaddress(host2)

if cmd != "login"

puts "Ошибка протокола: клиент послал сообщение #{msg}."

end

$list[player1] = [player2, addr, port, ipname, sess]

if match?(player1, player2)

# Имена теперь переставлены: если мы попали сюда, значит

# player2 зарегистрировался первым.

p1 = $list[player1]

р2 = $list[player2]

# ID игрока = name:ipname:color

# Цвет: 0=белый, 1=черный

p1id = "#{p1short}:#{p1[3]}:1"

p2id = "#{p2short}:#{p2[3]}:0"

sess1 = p1[4]

sess2 = p2[4]

sess1.puts "#{p2id}"

sess2.puts "#{p1id}"

sess1.close

sess2.close

Поделиться:
Популярные книги

Я все еще князь. Книга XXI

Дрейк Сириус
21. Дорогой барон!
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Я все еще князь. Книга XXI

Имя нам Легион. Том 9

Дорничев Дмитрий
9. Меж двух миров
Фантастика:
боевая фантастика
рпг
аниме
5.00
рейтинг книги
Имя нам Легион. Том 9

Тринадцатый VIII

NikL
8. Видящий смерть
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Тринадцатый VIII

Чужак из ниоткуда 3

Евтушенко Алексей Анатольевич
3. Чужак из ниоткуда
Фантастика:
космическая фантастика
альтернативная история
5.00
рейтинг книги
Чужак из ниоткуда 3

Шатун. Лесной гамбит

Трофимов Ерофей
2. Шатун
Фантастика:
боевая фантастика
7.43
рейтинг книги
Шатун. Лесной гамбит

Черный Маг Императора 15

Герда Александр
15. Черный маг императора
Фантастика:
юмористическое фэнтези
попаданцы
аниме
сказочная фантастика
фэнтези
фантастика: прочее
5.00
рейтинг книги
Черный Маг Императора 15

Черный Маг Императора 10

Герда Александр
10. Черный маг императора
Фантастика:
юмористическое фэнтези
попаданцы
аниме
сказочная фантастика
фэнтези
5.00
рейтинг книги
Черный Маг Императора 10

Идеальный мир для Лекаря

Сапфир Олег
1. Лекарь
Фантастика:
фэнтези
юмористическое фэнтези
аниме
5.00
рейтинг книги
Идеальный мир для Лекаря

Князь

Шмаков Алексей Семенович
5. Светлая Тьма
Фантастика:
юмористическое фэнтези
городское фэнтези
аниме
сказочная фантастика
5.00
рейтинг книги
Князь

Целеполагание

Владимиров Денис
4. Глэрд
Фантастика:
фэнтези
боевая фантастика
рпг
5.00
рейтинг книги
Целеполагание

Геном хищника. Книга четвертая

Гарцевич Евгений Александрович
4. Я - Легенда!
Фантастика:
боевая фантастика
рпг
попаданцы
5.00
рейтинг книги
Геном хищника. Книга четвертая

Неучтенный элемент. Том 3

NikL
3. Антимаг. Вне системы
Фантастика:
фэнтези
5.00
рейтинг книги
Неучтенный элемент. Том 3

Убивая маску

Метельский Николай Александрович
13. Унесенный ветром
Фантастика:
боевая фантастика
5.75
рейтинг книги
Убивая маску

Эволюционер из трущоб. Том 9

Панарин Антон
9. Эволюционер из трущоб
Фантастика:
попаданцы
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Эволюционер из трущоб. Том 9