О сайте
  Новости сайта
  Почитать
  Утилиты
 
  Help Blitz3D
 
   

 

 

 

 

 

 

 

 

 

 

Работа с Сетью в Blitz3D - UDP, TCP, FTP, HTTP

Автор: Tadeus (Progger_Leo)
e-mail или ICQ 420^069^087

UDP

Итак, что же такое UDP? UDP - это протокол негарантированной передачи данных. То есть, никто вам не гарантирует, что пакеты дойдут в целости и сохранности да еще и в нужном порядке. Вы спросите: а зачем он тогда? Дело в том, что отстутствие гарантии передачи данных дает нам большую скорость, нежели дает TCP. То есть, это самое оно, когда вы пишете сетевой шутер или action. UDP расположен непосредственно над протоколом IP, и впрочем, не очень от него отличается.

Теперь немного о портах. Порты до 1024 являются системными и использовать их в сетевых играх не стоит. Также следует поберечься от портов с номерами от 1024 до 49151 - они зарезервированы. Рекомендуется использовать порты с номерами от 49152 до 65535 - они динамические. В любом случае, если не указывать порт, Blitz3D вам сам найдет подходящий. На мой взгляд, автоматический выбор порта является оптимальным решением, однако и у него есть несколько недостатков.

Про IP-адрес, думаю, рассказывать много не придется. Единственное, что хочется упомянуть: в UDP используется целочисленный IP-адрес, а не текстового вида, вроде "127.0.0.1". Чтобы превратить из текстового вида в целочисленный, можно использовать следующую функцию:

Function Int_IP(IP$)
d1%=Left(IP$,Instr(IP$,".")-1):IP$=Right(IP$,Len(IP$)-Instr(IP$,"."))
d2%=Left(IP$,Instr(IP$,".")-1):IP$=Right(IP$,Len(IP$)-Instr(IP$,"."))
d3%=Left(IP$,Instr(IP$,".")-1):IP$=Right(IP$,Len(IP$)-Instr(IP$,"."))
d4%=IP$
Return (d1 Shl 24) + (d2 Shl 16) + (d3 Shl 8 ) +d4
End Function

Также, чтобы узнать все свои IP-адреса, нужно использовать такой код:

For i=1 To CountHostIPs("")
Print DottedIP(HostIP(i))
Next

В итоге на экране отобразятся все IP-адреса локальной машины. Почему их может быть много? Есть несколько причин: некоторое количество сетевых плат, прокси и т.д. Чтобы узнать внешний IP-адрес (то есть тот, который используется уже непосредственно), нужно либо считать его с какого-то сайта, где показывается IP-адрес, либо сделать такой сайт. В качестве первого, могу предложить http://checkip.dyndns.org, благо там нет ничего лишнего, кроме надписи "Current IP Address: ". Но это преодолевается за пару секунд.

Также следует учитывать, что UDP использует схему peer-to-peer, а это значит, что у нас нет ни серверов, ни клиентов, однако я буду употреблять термин "клиент" для обозначения программы, которая обменивается с нами по протоколу UDP. Так вот, такая архитектура построение клиентов означает, что, чтобы послать сообщение, надо указать IP-адрес клиента, которому вы, собственно, будете это сообщение посылать. Разумеется, необязательно вводить IP-адреса вручную, ведь это можно сделать программно, но об этом ниже.

Итак, давайте уже, наконец-то, приступим. Для начала надо создать отдельный сетевой поток на определенном порте. Как уже выше говорилось, надо брать номер от 49152 до 65535. Возьмем, к примеру, 53424.

Stream=CreateUDPStream(53424)

Итак, вот мы и создали поток. Кстати, если номер порта не указывается, то программа все равно будет нормально работать:

Stream=CreateUDPStream()

Но как можно узнать, какой же порт мы используем для приложения? Очень просто! UDPStreamPort(поток) вернет нам порт, к которому мы привязали наш поток. В скобках мы должны указывать имя нашего потока. Вот так:

Stream=CreateUDPStream()
Print UDPStreamPort(Stream)

Данная небольшая программа печатает на экране используемый нами порт.

Ну, все это детские забавы. Давайте займемся чем нибудь посерьезнее. Напишем, например, две программы. Одна будет посылать текст, другая - принимать. Для этого нам понадобятся две команды: SendUDPMsg и RecvUDPMsg. С помощью первой мы можем отправлять сообщения, вот так:

SendUDPMsg поток,IP_получателя[,порт_получателя]

Как видите, порт получателя указывать необязательно. Хочется сразу сказать, что лучше использовать многопоточный принцип, то есть для каждого клиента создавать отдельный поток со своим, особенным портом. Это поможет не возникать некоторым конфликтам. Да и удобнее. Также, в параметре IP_получателя должен указываться целочисленный адрес. Напоминаю, что функция, превращающая точечный адрес в целочисленный есть в начале статьи.

Далее, команда RecvUDPMsg. Синтаксис прост:

RecvUDPMsg(поток)

Эта функция возвращает IP-адрес отправителя, если сообщение пришло и 0 в том случае, если сообщение не пришло. Вообще, IP-адрес отправителя последнего сообщения можна также легко узнать с помощью функции UDPMsgIP:

UDPMsgIP(поток)

В скобках, разумеется, нужно указать поток, откуда должно прийти сообщение. Также можно получить порт, с которого пришло сообщение, с помощью похожей команды UDPMsgPort:

UDPMsgPort(поток)

Пожалуй, это все. Только осталось изучить одну команду - UDPTimeouts. Синтаксис таков:

UDPTimeouts миллисекунды

Указывает, с какой частотой RecvUDPMsg будет проверять наличие входящих сообщений. В основном применяется для контроля скорости приложения.

Итак, вы изучили команды, которые применяет UDP, пора написать то, что мы описывали раньше: два приложения, где одно посылает текст, а другое принимает.

stream=CreateUDPStream(53425)
Writeline stream,"1"
Writeline stream,"2"
SendUDPMsg stream,Int_IP("127.0.0.1"),53424
End

Function Int_IP(IP$)
d1%=Left(IP$,Instr(IP$,".")-1):IP$=Right(IP$,Len(IP$)-Instr(IP$,"."))
d2%=Left(IP$,Instr(IP$,".")-1):IP$=Right(IP$,Len(IP$)-Instr(IP$,"."))
d3%=Left(IP$,Instr(IP$,".")-1):IP$=Right(IP$,Len(IP$)-Instr(IP$,"."))
d4%=IP$
Return (d1 Shl 24) + (d2 Shl 16) + (d3 Shl 8 ) +d4
End Function

Как видно, в UDP можно формировать пакет из нескольких сообщений в одном. Так что, можно не объединять информацию в одну строку, а просто разместить правильно в одном пакете. Считывается такой пакет,кстати, тоже очень удобно. К слову, IP-адрес "127.0.0.1" всегда обозначает локальную машину, то есть сетевую игру можно будет легко и просто отлаживать.

Далее, пишем код второй программы:

stream=CreateUDPStream(53424)

While Not KeyHit(1)
If RecvUDPMsg(stream) Then
Print ReadLine$(stream)
Print ReadLine$(stream)
EndIf
Wend
End

Не забудьте, чтобы были разные порты у клиента и у сервера, иначе сообщение попросту не придет. Это касается локальной сети.

Как видите, многострочные пакеты весьма удобны. Однако, следует помнить, что в Интернете некоторые части пакетов могут потеряться и вы получите совсем не то, что было нужно.

Теперь о том, как не узнавать IP-адрес каждого клиента по отдельности, ибо сейчас мы обсудим принцип, по которому можно настроить UDP на архитектуру "клиент-сервер". В таком случае будет преимущество - нужно будет знать только один IP-адрес - сервера. Согласитесь, это куда удобнее. Как же будет действовать наша система? Все гениальное - просто. Мы посылаем сообщение серверу, что ,мол, подключаюсь, он регистрирует ваш IP-адрес и у себя и рассылает остальным ваш IP-адрес. Просто, не правда ли? Давайте посмотрим, как это реализовать в коде:

Global stream
Global is_server

Type Player
Field ip
End Type

Function Host()
stream=CreateUDPStream(53424)
is_server=True
End Function

Function Join(ipadress$)
stream=CreateUDPStream(5)
ip=Int_IP(ipadress$)
WriteLine stream,GetMyIP()
SendUDPMsg stream,ip,53424
End Function

Function UpdateNetwork()
If is_server Then
If RecvUDPMsg(stream) Then
p.Player=New Player
p\ip=Int_IP(ReadLine$(stream))
Endif
Endif
End Function

Function Int_IP(IP$)
d1%=Left(IP$,Instr(IP$,".")-1):IP$=Right(IP$,Len(IP$)-Instr(IP$,"."))
d2%=Left(IP$,Instr(IP$,".")-1):IP$=Right(IP$,Len(IP$)-Instr(IP$,"."))
d3%=Left(IP$,Instr(IP$,".")-1):IP$=Right(IP$,Len(IP$)-Instr(IP$,"."))
d4%=IP$
Return (d1 Shl 24) + (d2 Shl 16) + (d3 Shl 8 ) +d4
End Function

Function GetMyIP$()
Return DottedIP$(HostIP(CountHostIPs("")))
End Function

Давайте я дам краткое описание каждой функции, а с кодом вы разберетесь сами - я же не могу за вас все разжевывать. Итак, сначала мы создаем глобальные переменные: переменная потока и переменная, обозначающая, сервер мы или клиент. Первая функция создает поток сервера, и в переменную is_server записывает значение True. Вторая - сообщает серверу о себе, то есть мы становимся клиентом и посылаем серверу наш IP-адрес,а также выставляет значение is_server равное False. Третья функция служит для выполнения циклических действий на стороне сервера: прием сообщений, рассылка IP-адресов. Четвертую функцию вы уже знаете - она превращает IP-адрес из точечного в целочисленный. Наконец, пятая возвращает IP-адрес локальной машины, хоть и не точно. Как узнать точный IP-адрес, читайте вначале статьи. В качестве домашнего задания сделайте так, чтобы сервер рассылал IP-адреса одних клиентов другим. Я специально упустил этот момент, дабы дать вам область для тренировки.

Также привожу простейший пример использования - сервер выводит на экран подсоединенных игроков (пусть и не самым лучшим методом), а клиент сначала подключается и посылает о себе информацию. Код приводится без учета предыдущих функций.

Сервер:
Host()
While Not KeyDown(1)
Cls
For p.Player=Each Player
Print DottedIP$(p\ip)
Next
UpdateNetwork()
Wend

Клиент:
Join("127.0.0.1")
End

Как видите, все очень просто.

TCP

Итак, вы решили изучить основу многих протоколов высшего уровня, то бишь ТСР? Хорошо! Чем он хорош? Гарантией того, что сообщение придет в целости и сохранности. Однако, в результате этого мы теряем скорость. Целесообразно использовать ТСР там, где надежность важнее скорости. В ином случае - используйте UDP.

Начнем, пожалуй, с пары нюансов. Во-первых, ТСР использует архитектуру "клиент-сервер", что облегчает нам жизнь, и не нужно знать IP-адрес только сервера. В смысле - сначала. Во-вторых, тут насчет портов такой же принцип как и в UDP. Порты до 1024 являются системными и использовать их в сетевых играх не стоит. Также следует поберечься от портов с номерами от 1024 до 49151 - они зарезервированы. Рекомендуется использовать порты с номерами от 49152 до 65535 - они динамические. В отличие от UDP, в ТСР вам надо сразу определится с портом, ибо тут нет таких вольностей, как "обнаружение свободных портов".

Рассмотрев моменты, приступим к рассмотрению команд. Итак, так как в ТСР архитектура "клиент-сервер", значит, у нас имеется две команды инициализации сеанса: для сервера и для клиента. Для начала давайте разберемся с сервером.

поток_сервера=CreateTCPServer(порт)

Создает сервер потока ТСР на указанный порт и возвращает хэндл потока сервера. Возвращает 0, если неудачно, поток - если удачно. Про порты уже говорилось выше. Далее, для сервера, чтобы получать и писать сообщение, надо принимать входящий поток. Делается это командой AcceptTCPStream вот так:
поток=AcceptTCPStream(поток_сервера)

Думаю, в примере это будет смотреться понятнее:

svr=CreateTCPServer(80)
While Not KeyHit(1)
pot=AcceptTCPStream(svr)
Wend

Таким образом, мы создали сервер на порте 80. К слову, если вы на Блице пишете программу для работы с сетью (броузер, почтовый клиент и т.д.), то Вы, конечно же, можете использовать системные порты - они для того и предназначены. Однако, если вы создаете игру - берите динамический и только. Вернемся к коду. Мы каждый цикл пытаемся принять входящий поток, чтобы в цикле можно было соответственно читать и посылать информацию. Чтобы получить IP-адрес пославшего, используем функцию TCPStreamIP. Синтаксис:

переменная=TCPStreamIP(поток)
Возвращает целочисленный IP в переменную. Если вам надо получить точечный IP - смотрите в справке DottedIP$()

Также можно получить порт машины клиента функцией TCPStreamPort:
переменная=TCPStreamPort(поток)

Обьяснять, думаю не надо?

Теперь о передаче информации. А как же эта информация собственно посылается и получается? Очень просто! Вы, я думаю, уже работали с файлами, не так ли? Так вот, представьте, что ТСР-поток - это ваш файл и просто используйте команды для чтения в или из потока. Правда, с чтением есть еще один нюанс - надо проверять, пришла ли какая-то информация. Это очень просто! AcceptTCPStream возвращает 0, если ничего не пришло и поток для того, кто послал сообщение, если оно, собственно, было послано. И нужно учесть еще вот что - человек мог сделать запрос вот таким:

WriteLine pot,"1"
WriteLine pot,"2"
WriteLine pot,"3"

Как его считать? Опять таки, очень просто! С помощью, думаю, знакомой вам функции Eof:
Eof(поток)
Возвращает False, если информация в потоке еще не закончилась и True, если вся уже пришла и считана. Вот как это работает:

svr=CreateTCPServer(50000)
While Not KeyHit(1)
pot=AcceptTCPStream(svr)
If pot Then
While Not Eof(pot)
Print Readline$(pot)
Wend
Endif
Wend

Чтобы написать игроку, нужно писать именно на уникальный поток. Сейчас я вам покажу, как, собственно, получить этот поток:

Type Player
Field stream
End Type

svr=CreateTCPServer(50000)
While Not Keyhit(1)
pot=AcceptTCPStream(svr)
If pot Then
p.Player=New Player
p\stream=pot
Endif
Wend

Далее, чтобы получать сообщения не от новых игроков, а от тех, что уже записаны, используем следующую схему:

For p.Player=Each Player

If ReadAvail(p\stream) Then
...
Endif
Next

Думаю, все ясно как пень. Самая сложная часть позади. Теперь давайте о клиенте.

Подключается он командой OpenTCPStream. Синтаксис:
поток=OpenTCPStream(IP_сервера,порт)

Возвращает 0, если неуспешно, и поток - если успешно. Тут все проще, нежели у сервера. Просто посылаем информацию на этот же поток и все! Для наглядности пример:

pot=OpenTCPStream("prevedmedved.ru",80)
WriteLine pot,"PREVED!"

Вот и все! Что еще хотелось бы сказать, так это насчет посылания сообщения другим клиентам. Так вот. ВСЕ передается через сервер. Вот так вот. Если надо послать мессагу кому-то одному - шлем запрос серверу. Хотим всем - шлем запрос к серверу. И сервер должен все эти запросы отрабатывать.

Вот и закончили мы долбить второй основной протокол, поддерживаемый Блицем. А что это нам дает? Очень многое. Ведь нам открывается дорога к протоколам более высокого уровня.

FTP

Итак, сейчас я обучу вас использованию протокола FTP. Для тех кто не знает - это протокол передачи файлов на сервер. FTP - это протокол прикладного уровня, использующий ТСР. Чтобы использовать его, вам нужно знать как работать в ТСР клиентом. Если вы это знаете - то вы вполне готовы чтобы начать. Если же нет - прочитайте главу выше.

Для начала нам надо знать три вещи : адрес сервера, логин и пароль. Мы будем использовать в качестве первого - ftp.narod.ru, второго - test, третьего - tcp. Думаю, понятно. Открываем Explorer, вводим в заголовке адрес сервера, затем в окошке данные. Так мы будем следить за результатами нашей работы.

Ну-с, приступим. Сначала нам надо открыть поток на порте 21:
pot=OpenTCPStream("ftp.narod.ru",21)

Так, соединение открыто, давайте залогинимся. Следует также обрабатывать ошибки - кто знает, что там происходит на сервере?

Repeat
code=Int(ReadLine$(pot))
Select code
Case 220
WriteLine pot,"USER test"
Case 331
WriteLine pot,"PASS tcp"
Case 530
RuntimeError "Log on failed"
End Select
Until code=230

В случае удачи программа закончится. Итак, что же мы сделали? Сначала мы считываем данные, которые идут от сервера и с помощью функции Int получаем цифровой код, расположенный вначале. Далее проверяем - можно ли слать каждый из параметров. Когда пишет 220 - значит можно посылать логин, если 331 - можно посылать пароль, если пишет 530 - значит либо логин, либо пароль неверен. Либо оба неверны.

Теперь на сервер можно посылать команды управления файлами. К слову, процесс немного напоминает DOS. Итак, для начала давайте зальем какой нибудь файл. Давайте рисунок с именем "picture.jpg" Это делается командой STOR. Пишем значится вот так:
Writeline pot,"STOR picture.jpg"

Обновляем и вуаля! На FTP есть наша картинка. К счастью, тут проверять ничего не надо. И то хорошо. А теперь давайте эту картинку загрузим с FTP на наш компьютер. Командой RETR:
Writeline pot,"RETR picture.jpg"

Работает! Что еще нужно для счастья? А нужна возможность видеть папки, заходить в них, выходить и т.д. Короче, работа с иерархией каталогов. Давайте сначала попробуем создать папку. Пригодится нам команда MKD:
WriteLine pot,"MKD Pictures"

Здесь мы создаем на сервере папку Pictures. Что и наблюдаем в Explorer'е. Далее, нам же надо в эту директорию зайти? Тут уже используем команду CWD. А чтобы удостовериться, что мы действительно туда зайдем, закинем в нашу директорию файл picture.jpg:
WriteLine pot,"CWD Pictures"
WriteLine pot,"STOR picture.jpg"

Получилось. Что ж, весьма хорошо! А как нам вернутся в предыдущую папку? С помощью команды CDUP:
WriteLine pot,"CDUP"

Удаляется директория с помощью команды RMD:
WriteLine pot,"RMD Pictures"

Я забыл только рассказать, как удалять и переименовывать. Начнем с удаления. Используем команду DELE:
WriteLine pot,"DELE picture.jpg"

Далее переименовываем файлы:
WriteLine pot,"RNFR picture.jpg"
WriteLine pot,"RNTO risunok.jpg"

Первая строка выбирает файл,имя которого нужно переименовать, а вторая - в какое имя надо превратить.

Наконец, после необходимой работы, надо закрыть сеанс связи командой QUIT и закрытием потока. Вот так:
WriteLine pot,"QUIT"
CloseTCPStream pot

Вот и все!

HTTP

Итак, давайте сначала объясню для тех кто не знает: HTTP (с англ. HyperText Transfer Protocol) - протокол передачи гипертекста или,если проще, web--страниц. Где он используется? Да практически везде! Если раньше, использовали только для получения web-страниц, то сейчас его используют в MMORPG. Примеры? Да почти все они на нем основанны. Но если все же вам нужен пример, я его приведу: World of Warcraft. Но я буду (по крайней мере в этой статье) описывать HTTP как средства доступа к ресурсам Интернета и взаимодействия с этими ресурсами.

Далее, HTTP стоит над ТСР и использует порт 80. Для того, чтобы продолжить, вы должны уметь работать с ТСР. Ну-с, приступим.

Какой сайт мы будем получать? Давайте офф. сайт Блица:

pot=OpenTCPStream("www.blitzbasic.com",80)
WriteLine pot,"GET /index.php HTTP/1.0"
WriteLine pot,Chr$(10)
While Not Eof(pot)
Print ReadLine$(pot)
Wend
WaitKey
End

Запускаем и ура, получилось! Итак, сначала мы открываем поток на адрес www.blitzbasic.com на порте 80. Затем мы подаем туда запрос GET. Что в этом запросе надо указывать? Во-первых, нужную страницу. Если указывается общий адрес, вида www.microsoft.com, www.blitzbasic.com, www.icq.com и т.д., то загружается страница с именем index: index.htm, index.php и т.д. Далее идет версия протокола. Вообще, следует посмотреть, какую версию HTTP использует сервер и потом уже слать запрос. На некоторых неправильно срабатывает запрос с версией 1.0, на других - с 1.1 короче надо проверять. Далее, мы посылаем символ Chr$(10), то есть переход на новую строку, чтобы показать, что текст запроса окончен.

Продолжим. Желательно также вставлять в запрос команду Host - она показывает к какому серверу подключатся. Вы спросите, но ведь мы адресс сервера указали в OpenTCPStream! Зачем еще раз? Ответ прост: прокси. То есть если у вас Интернет через прокси, то в OpenTCPStream вы должны указать IP-адрес прокси и обязательно указать Host. Чтобы правильно подключиться. Приведу пример с функцией:

Global BR$ = Chr$(13)+Chr$(10)

;1. обычный запрос веб-страницы
tcp = GetHttp("www.microsoft.com")
If tcp = False RuntimeError "unable to connect to web server"
While Eof(tcp) = False
Print ReadLine$(tcp)
Wend
CloseTCPStream(tcp)

; 2. запрос страницы через прокси-сервер с адресом 192.168.0.1 и портом 80
tcp = GetHttp("www.microsoft.com", 80,"192.168.0.1", 80)
If tcp = False RuntimeError "unable to connect to web server"
While Eof(tcp) = False
Print ReadLine$(tcp)
Wend
CloseTCPStream(tcp)
WaitKey
End

;========================================
Function GetHttp(server$, port=80, proxy$="",proxyport=0)
Local www
If Len(proxy$) = 0 proxy$ = server$
If proxyport = 0 proxyport = port
www = OpenTCPStream(proxy$,proxyport)
If www = False Return False
WriteLine www,"GET http://" + server$ + ":" + port + path$ + " HTTP/1.1" + BR$ + "Host: " + server$ + BR$ + "User-Agent: blitzbasic" + BR$ + "Accept: */*" + BR$
Return www
End Function

Ах, да. Просматривая функцию вы могли заметить неизвестные команды. Также видно, что они разделены символом Chr$(13)+Chr$(10) Что ж, так тоже можно, а теперь насчет команд:

User-Agent: blitzbasic
Используется, чтобы показать, через какую программу делается запрос. Не особо существенно, честно говоря.

Accept: */*
Честно говоря, с этой командой не разобрался.

Также вы можете заметить, что уже в данном примере, используется версия 1.1

Вот. Теперь, пожалуй, самый часто задаваемый вопрос по HTTP: допустим, на странице есть формы, как эти формы заполнить и отправить на сервер? Из программы. Это несложно. Но для начала немного теории. Для отправки данных есть два метода GET и POST. В чем различие? А в том, что с помощью GET-метода ты как бы передаешь через адрес, а с методом POST - напрямую. В связи с этим, хочется сказать, если есть форма, содержимое которой посылается на e-mail, там ВСЕГДА должен быть записан и использован метод POST.

Далее, предполагается, что вы хотя бы немного знаете HTML - язык разметки гипертекста. Тэкс, открываем блокнот и пишем значится:

<form action="login.php" method=get enctype=text/plain>
Логин:
<input type=text name=login>
Пароль:
<input type=text name=password>
</form>

Итак, мы создали такую вот страничку в Интернете. Теперь, как из Блица послать на login.php данные? В данном случае мы сделаем методом GET:

pot=OpenTCPStream("vasya.com")
WriteLine pot,"GET login.php?login=Vasya&password=qwerty HTTP/1.0"
WriteLine pot,"Host: vasya.com"
WriteLine pot,Chr$(10)
While Not Eof(pot)
Print ReadLine$(pot)
Wend
WaitKey
End

Как я уже говорил, при GET-методе параметры передаются в заголовке. Далее, считываем, что нам отвечает сервер. Не правда ли просто? А теперь давайте тоже повторим с методом POST. Не забудьте на нашей web-странице в теге <form> заменить параметр method=get на method=post. Далее код для Блица:

pot=OpenTCPStream("vasya.com")
WriteLine pot,"POST login.php HTTP/1.0"
WriteLine pot,"Host: vasya.com"
WriteLine pot,Chr(13)+Chr(10)
WriteLine pot,"login=Vasya&password=qwerty"

Как видите, команды непосредственно разделены от параметров строкой Chr(13)+Chr(10).

Тэкс, запускаем из формы. Работает...Из блица. Ура!

Заключение

Теперь вы знаете как работать с основными протоколами. Теперь вы можете написать динамическую сетевую игру. Между прочим, одна из известных онлайновых ролевых игр, написанных на Блице (их кстати, немного) использовала сетевую библиотеку BlitzPlay, которая в свою очередь использовала UDP. В-общем, желаю вам успехов и удачи в проектах.

С Уважением, Волошин Леонид аka Tadeus.

 

     
     
     
Hosted by uCoz