BASIC-256. Глава 20
Методические материалыАвтор: Владимир Черный
Этой главой мы завершаем публикацию перевода книги Джеймса Рено. Далее в книге только технические приложения. Всю эту информацию можно взять из справочника внутри самой программы или из сети. Эту главу перевел Владимир Черный.
Оглавление:
- Глава 1: Знакомство с BASIC-256 – cкажи «Привет»
- Глава 2: Рисуем основные фигуры
- Глава 3: Звуки и музыка
- Глава 4: Мыслить как программист
- Глава 5: Программа задает вам вопросы
- Глава 6: Сравнения, сравнения, сравнения
- Глава 7: Циклы и счетчики — повторяем снова и снова
- Глава 8: Графика на заказ — создание фигур своими руками
- Глава 9: Подпрограммы — повторное использование кода
- Глава 10: Управляем мышкой, перемещаем объекты
- Глава 11: Использование клавиатуры для управления программой
- Глава 12: Картинки, музыка и спрайты
- Глава 13 Массивы — коллекции данных
- Глава 14 Математика — развлечемся с числами
- Глава 15 Работаем со строками
- Глава 16 Файлы. Сохраним информацию на будущее
- Глава 17 Стеки, очереди, списки и сортировка
- Глава 18 Ловушки для ошибок времени исполнения
- Глава 19 Программирование баз данных
Глава 20. Сетевые соединения
В этой главе мы обсудим как использовать сетевые возможности BASIC-256. Сетевые функции в BASIC-256 реализованы как простое соединение через сокет с использованием TCP протокола (Transmission Control Protocol — протокол управления передачей). Здесь вы не найдете полного введения в программирование для TCP/IP сокетов.
Соединение с сокетом
Сетевые сокеты создают соединение между двумя компьютерами или программами. Пакеты с информацией могут быть отправлены или получены в двух направлениях через такое соединение.
Рисунок 35 Взаимодействие между сокетами.
Когда вы звоните по телефону, то вы (как клиент) должны знать номер телефона абонента, кому вы звоните (он — сервер). Мы называем такие номера — IP-адрес. BASIC-256 использует IP-адреса версии 4, которые обычно записывают четырьмя десятичными числами, разделенными точкой (A.B.C.D, где A,B,C и D в диапазоне от 0 до 255).
Дополнительно к IP-адресу сервера, клиент и сервер должны общаться через определенный порт. Можно представлять порт, как дополнительный номер к многоканальному телефонному номеру. Если вам (как клиенту) нужен определенный человек в большой компании (имеющей один общий входящий номер), то вам необходимо набрать дополнительно внутренний номер (порт) в ответ на сообщение (телефонного сервера) о соединении с общим номером компании (IP-адресом).
Номера портов могут быть любыми в диапазоне от 0 до 65535, но обычно порты в диапазоне от 0 до 1023 заняты различными системными службами (приложениями), поэтому такие порты не следует использовать.
Пример простого сервера и клиента.
1 # simple_server.kbs пример сервера
2 print "Прием запросов по порту 9999 на IP:" + netaddress()
3 NetListen 9999
4 NetWrite "Тестовое сообщение простого сервера."
5 NetClose
Программа 106 Простой сервер
1 # simple _client.kbs пример клиента
2 input "Введите IP-адрес сервера: ", addr$
3 if addr$ = "" then addr$ = "127.0.0.1"
4 #
5 NetConnect addr$, 9999
6 print NetRead
7 NetClose
Программа 107 Простой клиент.
Прием запросов по порту 9999 на IP:10.1.2.103
Пример вывода программы 106 Простой сервер
Введите IP-адрес сервера:
Тестовое сообщение простого сервера.
Пример вывода программы 107 Простой клиент
netaddress netaddress() Эта функция возвращает числовой Ipv4 адрес сетевого компьютера |
netlisten номер_порта netlisten (номер_порта) netlisten номер_сокета, номер_порта netlisten (номер_сокета, номер_порта) Открывает сетевое соединение (со стороны сервера) на указанном порту и ожидает соединений от других программ. Если номер_сокета не указан, используется нулевой (0) номер. |
netclose netclose() netclose номер_сокета netclose (номер_сокета) Завершает указанное сетевое соединение (сокет). Если номер_сокета не указан, сокет с номером ноль (0) будет закрыт. |
netwrite строка netwrite (строка) netwrite номер_сокета, строка netwrite (номер_сокета, строка) Посылает текстовое сообщение в указанное сетевое соединение. Если номер_сокета не указан, используется нулевой (0) номер. |
netconnect имя_сервера, номер_порта netconnect (имя_сервера, номер_порта) netconnect номер_сокета, имя_сервера, номер_порта netconnect (номер_сокета, имя_сервера, номер_порта) Открывает соединение с сервером со стороны клиента по указанному порту. В параметре имя_сервера указывается IP адрес или сетевое имя сервера. Если номер_сокета не указан, используется нулевой (0) номер. |
netread netread() netread (номер_сокета) Читает данные из указанного сетевого соединения и возвращает в виде текстовой строки. Эта функция является блокирующей — она ждет, пока данные не будут получены. Если номер_сокета не указан, используется нулевой (0) номер. |
Сетевой чат
Следующий пример использует еще одну сетевую функцию (netdata). Использование этой новой функции позволит нашему сетевому клиенту обрабатывать такие события, как нажатия клавиш и чтение сетевых данных только тогда, когда они действительно есть.
Программа сетевого чата (программа 108) комбинирует в себе и свойства сервера и свойства клиента. Если при запуске программы она не сможет соединиться с сервером, это событие будет перехвачено и, программа сама станет сервером. Это один из многих способов дать возможность одной программе выполнять как клиентскую, так и серверную роли.
1 # chat.kbs чат
2 # использует порт 9999 когда работает сервером
3
4 input "Адрес сервера чата (ввод для локальной машины)?", addr$
5 if addr$ = "" then addr$ = "127.0.0.1"
6 #
7 # Пробуем соединиться с сервером, если неудачно - становимся сервером сами
8 OnError startserver
9 NetConnect addr$, 9999
10 OffError
11 print "Соединение с сервером установлено"
12
13 chatloop:
14 while true
15 # получаем код нажатой клавиши и отсылаем его
16 k = key
17 if k <> 0 then
18 gosub show
19 netwrite string(k)
20 end if
21 # получаем данные из сети и показываем их
22 if NetData() then
23 k = int(NetRead())
24 gosub show
25 end if
26 pause .01
27 end while
28 end
29
30 show:
31 if k=16777220 then
32 print
33 else
34 print chr(k);
35 end if
36 return
37
38 startserver:
39 OffError
40 print "Сервер запущен, ждем чат-клиента"
41 NetListen 9999
42 print "Клиент установил соединение"
43 goto chatloop
44 return
Программа 108 Сетевой чат
Запустите две копии BASIC-256 с программой 108 Сетевой чат. На первой запущенной копии заработает сервер, а на второй клиент. На клиенте напишите «Привет сервер!», а на сервере напишите в ответ «Привет клиент!». Вывод программы для сервера и для клиента приведены ниже.
Адрес сервера чата (ввод для локальной машины)?
Сервер запущен, ждем чат-клиента
Клиент установил соединение
ПРИВЕТ СЕРВЕР !
ПРИВЕТ КЛИЕНТ !
Пример вывода программы 108.1 Сетевой чат со стороны сервера
Адрес сервера чата (ввод для локальной машины)?
Соединение с сервером установлено
ПРИВЕТ СЕРВЕР !
ПРИВЕТ КЛИЕНТ !
Пример вывода программы 108.2 Сетевой чат со стороны клиента.
netdata netdata() Возвращает истину (true), если есть сетевые данные ожидающие чтения. Это позволяет программе продолжать работать без ожидания прибытия сетевого пакета. |
Большая программа этой главы создает сетевую аркадную игру в танки для двух игроков.
У каждого из игроков на экране имеется белый танк (свой) и черный танк (чужой). Используя стрелки можно управлять движением танка. Стреляем пробелом. |
1 # battle.kbs танковое сражение
2 # используем порт 9998 когда сервер
3
4 kspace = 32
5 kleft = 16777234
6 kright = 16777236
7 kup = 16777235
8 kdown = 16777237
9 dr = pi / 16 # смена направление
10 dxy = 2.5 # скорость передвижения
11 scale = 20 # размер танка
12 shotscale = 4 # размер снаряда
13 shotdxy = 5 # скорость снаряда
14 port = 9998 # номер порта для связи с сервером
15
16 dim tank(30)
17 tank = {-1,-.66, -.66,-.66, -.66,-.33, -.33, -.33, 0,-1, .33,-.33, .66,-.33, .66,-.66, 1,-.66, 1,1, .66,1, .66,.66, -.66,.66, -.66,1, -1,1}
18 dim shot(14)
19 shot = {0,-1, .5,-.5, .25,0, .5,.75, -.25,.75, -.25,0, -.5,-.5}
20
21 print "Танковое сражение - вы на белом танке."
22 print "Ваша задача поразить выстрелом черный"
23 print "танк. Используйте стрелки для перемещения"
24 print "и пробел для стрельбы."
25 print
26 input "Адрес сервера (ввод для локальной машины)?", addr$
27 if addr$ = "" then addr$ = "127.0.0.1"
28
29 # Пробуем соединиться с сервером, если неудачно - становимся сервером сами
30 OnError startserver
31 NetConnect addr$, port
32 OffError
33 print "Соединение с сервером установлено"
34
35 playgame:
36
37 myx = 100
38 myy = 100
39 myr = 0
40 # Позиция снаряда (для себя): направление и оставшееся расстояние
41 # (снарядов нет, если mypl=0)
42 mypx = 0
43 mypy = 0
44 mypr = 0
45 mypl = 0
46 yourx = 200
47 youry = 200
48 yourr = pi
49 # Позиция снаряда (для противника): направление и оставшееся расстояние
50 # (снарядов нет, если yourpl=0)
51 yourpx = 0
52 yourpy = 0
53 yourpr = 0
54 yourpl = 0
55 gosub writeposition
56
57 fastgraphics
58 while true
59 # Получаем значение нажатой клавиши и перемещаем танк на экране
60 k = key
61 if k <> 0 then
62 if k = kup then
63 myx = myx + sin(myr) * dxy
64 myy = myy - cos(myr) * dxy
65 end if
66 if k = kdown then
67 myx = myx - sin(myr) * dxy
68 myy = myy + cos(myr) * dxy
69 end if
70 if k = kspace then
71 mypr = myr
72 mypx = myx + sin(mypr) * scale
73 mypy = myy - cos(mypr) * scale
74 mypl = 100
75 end if
76 if myx < scale then myx = graphwidth - scale
77 if myx > graphwidth-scale then myx = scale
78 if myy < scale then myy = graphheight - scale
79 if myy > graphheight-scale then myy = scale
80 if k = kleft then myr = myr - dr
81 if k = kright then myr = myr + dr
82 gosub writeposition
83 end if
84 # перемещаем свой снаряд (если есть снаряды)
85 if mypl > 0 then
86 mypx = mypx + sin(mypr) * shotdxy
87 mypy = mypy - cos(mypr) * shotdxy
88 if mypx < shotscale then mypx = graphwidth - shotscale
89 if mypx > graphwidth-shotscale then mypx = shotscale
90 if mypy < shotscale then mypy = graphheight - shotscale
91 if mypy > graphheight-shotscale then mypy = shotscale
92 if (mypx-yourx)^2 + (mypy-youry)^2 < scale^2 then
93 NetWrite "!"
94 print "Противник убит, Игра закончена."
95 end
96 end if
97 mypl = mypl - 1
98 gosub writeposition
99 end if
100 # Получаем из сети позицию
101 gosub getposition
102 #
103 gosub draw
104 #
105 pause .1
106 end while
107
108 writeposition: ###
109 # 10 символов для x, 10 символов для y, 10 символов для r (поворот)
110 position$ = left(myx + " ",10)+left(myy + " ",10)+left(myr + " ",10)+left(mypx + " ",10)+left(mypy + " ",10)+left(mypr + " ",10)+left(mypl + " ",10)
111 NetWrite position$
112 return
113
114 getposition: ###
115 # Получаем из сети позицию и устанавливаем переменные для противника
116 while NetData()
117 position$ = NetRead()
118 if position$ = "!" then
119 print "Вы убиты. Игра окончена."
120 end
121 end if
122 yourx = 300 - float(mid(position$,1,10))
123 youry = 300 - float(mid(position$,11,10))
124 yourr = pi + float(mid(position$,21,10))
125 yourpx = 300 - float(mid(position$,31,10))
126 yourpy = 300 - float(mid(position$,41,10))
127 yourpr = pi + float(mid(position$,51,10))
128 yourpl = pi + float(mid(position$,61,10))
129 end while
130 return
131
132 draw: ###
133 clg
134 color green
135 rect 0,0,graphwidth,graphheight
136 color white
137 stamp myx, myy, scale, myr, tank
138 if mypl > 0 then
139 stamp mypx, mypy, shotscale, mypr, shot
140 end if
141 color black
142 stamp yourx, youry, scale, yourr, tank
143 if yourpl > 0 then
144 color red
145 stamp yourpx, yourpy, shotscale, yourpr, shot
146 end if
147 refresh
148 return
149
150 startserver:
151 OffError
152 print "Сервер запущен, ожидаем присоединения клиента"
153 NetListen port
154 print "Клиент соединился с сервером"
155 goto playgame
156 return
Программа 109 Танковое сражение по сети1
Пример графического экрана программы 109 Танковое сражение по сети.
———————————————-
1Программа нуждается в доработке: а) Выстрел в сторону может попасть в противника, т. к. поле рассматривается как сферическое, при этом снаряд может пройти и через ваш танк, не причинив ему вреда, что довольно странно б) Если первый выстрел еще не долетел, а вы выстрелили вновь — первый выстрел пропадет (прим. редактора).
Где скачать BASIC-256:
Для дистрибутивов ALT Linux
- ветка 4.0 basic256-0.9.6-alt5.M40.1.i586.rpm
- ветка 4.1 basic256-0.9.6-alt5.M41.1.i586.rpm
- ветка p5 basic256-0.9.6-alt5.M50P.1.i586.rpm
- ветка 5.1 basic256-0.9.6-alt5.M51.1.i586.rpm
Windows версия
http://basic256.org (http://www.sourceforge.net/projects/kidbasic)
Как установить BASIC-256 в Linux
Для Альт Линукс: настроить репозиторий и обновить/установить пакет через synaptic или apt
Для rpm-based дистрибутивов: rpm -Uvh <имя_пакета>.rpm
Март 22, 2011, 5:51 пп
Компилятор Gambas IDE, входящий в состав AltLinux Юниор (gnome), ориентирован на синтаксис Basic256?
Практически VBasic
Март 22, 2011, 6:53 пп
В Юниоре и сам Basic256 имеется.
Март 23, 2011, 5:52 пп
Есть-есть..
Просто заглянул в Gambas -> набросал графическое приложение на Basic -> скомпилировал -> запустил = работает
В gambas удивила библиотека форм по задачам, от переключателей, прогресса до БД и web. В path добавил каталог и запускай свои программки по alt-f2, или с рабочего стола (по файл-ссылке).
Вот только как быть с открытостью? Код двоичный.
Март 29, 2011, 9:41 дп
Gambas и создавался как свободная альтернатива VBasic. Жаль только, что он не кроссплатформенный…
Март 31, 2011, 6:55 пп
Сегодня первую задачку доделал в Gambas
Описание закончу — опубликуем..
Первое впечатление:
1. по работе с директориями и файлами с VB есть различия.
2. математ. функции, работа со строками — идентична.
3. Среда значительно проще Lazarus, т.е. с первого занятия (после получения навыков алгоритмики, конечно) можно садить учеников и конструировать.
4. Поддержка БД
5. В рунете пока мало информационных ресурсов по Gambas
6. При сборки rpm-пакетов представлены только ОС Fedora, Mandriva и Suse
Март 31, 2011, 7:08 пп
Для нас уже кросплатформенность состоит в выборе между AltLinux, Ubuntu, Suse..
Думаю, что если вести занятия по программированию в старших классах, или кружках, первых курсах вуза, то ученики справятся в установке Линукс в качестве второй ОС, как минимум.
p.s. а Gambas интересен, руки чешутся