forum.boolean.name

forum.boolean.name (http://forum.boolean.name/index.php)
-   BlitzMax (http://forum.boolean.name/forumdisplay.php?f=104)
-   -   RakNet : большое время доставки пакетов (http://forum.boolean.name/showthread.php?t=5941)

jimon 21.04.2008 14:56

RakNet : большое время доставки пакетов
 
разбирался вчера с RakNet, хорошая либа
работает с UDP, имеет встроенные средства доссылки пакетов,
проверки на целостность, отправки файлов и тд и тп

только вот время доставки пакета туда и обратно между
двумя прогами на одном компе было около 70 мс
что меня жутко ужасало

воспользовался встроеным средством для пинга, возращает 0-1 мс
так вчера (уже сегодня) и уснул не разобравшись
на свежую голову написал все на чистом использовании функций RakNet
и нашол боттлнек !

либа работает на потоках, отсылка и прием сообщений не задерживают цикл проги
после отсылки пакета с клиента на сервер, я убирал delay(1)
из цикла клиента (типа ожидание пакета), но не учел того
что программа тогда перехватывает все ресурсы себе
и остальным уже мало что остается

по-скольку под RakNet очень мало примеров для BMax то
выкладываю суда код тестовой проги :
(может кому интересно будет)

Код:

SuperStrict
Framework brl.basic
Import pub.win32

Include "RakNet.bmx"

Const ID_P_TEST% = 101
Const PacketTestSize% = 32

Global Cycles% = 1000
Global DelayEnable% = True
Global RNDelay% = 1
Global Run% = True
Global EnableServer% = 1
Global EnableClient% = 1

Global ServerPeer%
Global ClientSystemAdress%

Global ClientPeer%
Global ServerSystemAdress%

Global PingSend%
Global PingRecive%
Global WaitPing%

If EnableServer Then CreateServer(7890)
If EnableClient Then CreateClient("127.0.0.1",7890)

L("Test Run")
While Run
        If EnableServer Then UpdateServer()
        If EnableClient Then UpdateClient()

        'Cycles:-1
        'If Cycles<0 Then Run = False
       
        If DelayEnable Then
                Delay(RNDelay)
        End If
Wend
L("Test Stop")

If EnableClient Then FreeClient()
If EnableServer Then FreeServer()

End

Function CreateServer(port%,max_connections% = 32)
        ServerPeer = RN_GetRakPeerInterface()
        Local err% = RN_Startup(ServerPeer, max_connections, RNDelay, port)
        RN_SetMaximumIncomingConnections(ServerPeer,max_connections)
        If err Then
                L("RN OpenServer")
        Else
                L("RN OpenServer Failed")
                End
        End If
        L("Create Server Ok")
End Function

Function UpdateServer()
        Local Packet% = RN_Receive(ServerPeer)
       
        If Packet Then
                Local BitPacket% =        RN_BitStreamCreateFromPacket(Packet)
                Local MsgType% =        RN_BitStreamReadChar(BitPacket)
                Local SysAddress% = RN_PacketGetSystemAddress(Packet)
                Local UserIndex% =        RN_GetIndexFromSystemAddress(ServerPeer, SysAddress)
               
                Select MsgType
                Case ID_REMOTE_DISCONNECTION_NOTIFICATION
                        L("Client has disconnected.")
                Case ID_REMOTE_CONNECTION_LOST
                        L("Client has lost the connection.")
                Case ID_REMOTE_NEW_INCOMING_CONNECTION
                        L("Client has connected.")
                'Case ID_CONNECTION_REQUEST_ACCEPTED
                '        systemAddressServer = RN_PacketGetSystemAddress(packet)
                '        L("Our connection request has been accepted.")
                Case ID_NEW_INCOMING_CONNECTION
                        ClientSystemAdress = SysAddress
                        L("A connection is incoming.")
                'Case ID_NO_FREE_INCOMING_CONNECTIONS
                '        L("The server is full.")
                Case ID_DISCONNECTION_NOTIFICATION
                        L("A client has disconnected.")
                Case ID_CONNECTION_LOST
                        L("A client lost the connection.")
                Case ID_P_TEST
                        Local Test%
                        For Local i% = 1 To PacketTestSize
                                Test = RN_BitStreamReadInt(BitPacket)
                        Next
                        L("Server Recive Ping,resend")
                        SendTest(ServerPeer,SysAddress)
                Default
                        L("Message with identifier " + MsgType + " has arrived.")
                End Select
               
                RN_BitStreamDestroy(BitPacket)
                RN_DeallocatePacket(ServerPeer, Packet)
        End If

End Function

Function SendTest(Peer%,Adress%)
        Local BitStream% = RN_BitStreamCreate1(0)
        RN_BitStreamWriteChar(BitStream,ID_P_TEST)
        For Local i% = 1 To 32
                RN_BitStreamWriteInt(BitStream,Rand(0,65535))
        Next
        RN_BitStreamSetNumberOfBitsAllocated(BitStream, RN_BitStreamGetNumberOfBitsUsed(BitStream))
        RN_SendBitStream(Peer, BitStream, HIGH_PRIORITY, RELIABLE_ORDERED, 0, Adress, False)
        RN_BitStreamDestroy(BitStream)
End Function

Function FreeServer()
        RN_Shutdown(ServerPeer, 100)
        ServerPeer = RN_DestroyRakPeerInterface(ServerPeer)
        L("Free Server Ok")
End Function

Function CreateClient(ip$,port%)
        ClientPeer = RN_GetRakPeerInterface()
        RN_Startup(ClientPeer,1,RNDelay,0)
        Local err% = RN_Connect(ClientPeer,ip,port,"",0);
        If err Then
                L("RN OpenClient")
        Else
                L("RN OpenClient Failed")
                End
        End If
        L("Create Client")
End Function

Function UpdateClient()
        Local Packet% = RN_Receive(ClientPeer)
       
        If Packet Then
                Local BitPacket% =        RN_BitStreamCreateFromPacket(Packet)
                Local MsgType% =        RN_BitStreamReadChar(BitPacket)
                Local SysAddress% = RN_PacketGetSystemAddress(Packet)
                Local UserIndex% =        RN_GetIndexFromSystemAddress(ClientPeer, SysAddress)
               
                Select MsgType
                Case ID_REMOTE_DISCONNECTION_NOTIFICATION
                        L("Client has disconnected.")
                Case ID_REMOTE_CONNECTION_LOST
                        L("Client has lost the connection.")
                Case ID_REMOTE_NEW_INCOMING_CONNECTION
                        L("Client has connected.")
                Case ID_CONNECTION_REQUEST_ACCEPTED
                        ServerSystemAdress = RN_PacketGetSystemAddress(Packet)
                        L("Our connection request has been accepted.")
                'Case ID_NEW_INCOMING_CONNECTION
                '        ClientSystemAdress = SysAddress
                '        L("A connection is incoming.")
                Case ID_NO_FREE_INCOMING_CONNECTIONS
                        L("The server is full.")
                Case ID_DISCONNECTION_NOTIFICATION
                        L("we disconnected.")
                Case ID_CONNECTION_LOST
                        L("we lost the connection.")
                Case ID_P_TEST
                        Local Test%
                        For Local i% = 1 To PacketTestSize
                                Test = RN_BitStreamReadInt(BitPacket)
                        Next
                        PingRecive = MilliSecs()
                        WaitPing = 0
                        L("Client Recive Ping, delta : "+(PingRecive-PingSend))
                Default
                        L("Message with identifier " + MsgType + " has arrived.")
                End Select               
               
                RN_BitStreamDestroy(BitPacket)
                RN_DeallocatePacket(ClientPeer, Packet)
        End If
       
        If (Not WaitPing) And ((MilliSecs() - PingRecive)>500) And ServerSystemAdress Then
                SendTest(ClientPeer,ServerSystemAdress)
                PingSend = MilliSecs()
                WaitPing = 1
                L("Client Send Ping")
        End If
       
        If WaitPing And (MilliSecs() - PingSend)>400 Then
                WaitPing = 0
                L("out time")
        End If
       
End Function

Function FreeClient()
        RN_CloseConnection(ClientPeer,RN_GetSystemAddressFromIndex(ClientPeer, 0), True)
        RN_Shutdown(ClientPeer, 100)
        ClientPeer = RN_DestroyRakPeerInterface(ClientPeer)
        L("Free Client Ok")
End Function

Function L(line$)
        DebugLog line
End Function

эта версия программы конектится сама на себя
с помощью EnableServer и EnableClient переменных можно
сделать отдельно как сервер так и клиент

время отсылки пакета на сервер и обратно около 4 мс
(все засыпания длятся около 3.5 мс, так что входит в норму)

библиотека имеет контроль потока, стабилизация пинга
произойдет через 10-20 пакетов

скачать враппер вы можете сдесь :
http://repeatuntil.free.fr/raknet/index.html

FDsagizi 21.04.2008 22:25

Ответ: RakNet : большое время доставки пакетов
 
Главные тесты это через инет!

jimon 22.04.2008 00:32

Ответ: RakNet : большое время доставки пакетов
 
FDsagizi
тестить пока не с кем :( у меня нету внешнего ip

moka 22.04.2008 15:08

Ответ: RakNet : большое время доставки пакетов
 
С проксями и внутренним Ip как понял голименько получается?
jimon, если у тебя открытые есть порты, и не прокси - тогда у тебя всё должно прокатить, главное узнай свой внешний Ip, можешь тут: http://www.utorrent.com/testport.php?port=30001 заодно и порт найди открытый.

jimon 22.04.2008 22:16

Ответ: RakNet : большое время доставки пакетов
 
MoKa
не работает, с другого компа даже мой комп не могут по-пинговать
хотя аутпост и все остальное отключено

moka 23.04.2008 11:58

Ответ: RakNet : большое время доставки пакетов
 
jimon, тогда твой провайдер - паскуда..

Tadeus 23.04.2008 14:16

Ответ: RakNet : большое время доставки пакетов
 
Цитата:

Сообщение от MoKa (Сообщение 79919)
jimon, тогда твой провайдер - паскуда..

Зато скорость гут :-)

GoodWin 23.04.2008 17:30

Ответ: RakNet : большое время доставки пакетов
 
Народ, а кто знает какой номер у последней версии врапера raknet для Блитца? а то я запутался... ( у мну есть: www.lcuriel.arrakis.es/raknetwrapper2483.rar и RakNetWrapper3.00_release)

jimon 23.04.2008 18:33

Ответ: RakNet : большое время доставки пакетов
 
GoodWin
как я знаю - RakNetWrapper3.00_release последняя

GoodWin 23.04.2008 18:49

Ответ: RakNet : большое время доставки пакетов
 
просто я в 3 версии не нашел вот этих вот функций:
RN_CreatePlayerIDFromPacket(packet)
RN_ServerGetPlayerIPFromID(server,PlayerID)
или я слепой? или может кто подскажет как их реализовать?

jimon 23.04.2008 19:53

Ответ: RakNet : большое время доставки пакетов
 
вот из RakNet.bmx нужные функции :
RN_GetIndexFromSystemAddress
RN_GetSystemAddressFromIndex
RN_PacketGetplayerIndex
RN_PacketGetSystemAddress

GoodWin 23.04.2008 21:18

Ответ: RakNet : большое время доставки пакетов
 
Цитата:

Сообщение от jimon (Сообщение 79953)
вот из RakNet.bmx нужные функции :
RN_GetIndexFromSystemAddress
RN_GetSystemAddressFromIndex
RN_PacketGetplayerIndex
RN_PacketGetSystemAddress


RN_PacketGetplayerIndex - это понятно, но только на стороне сервера можно получить
RN_GetIndexFromSystemAddress(rakPeerInterface,syst emAddress)
- а это функция возвращает индекс (индекс чего?) по системному адресу (что за адрес такой и как его получить (подозреваю, что RN_PacketGetSystemAddress%(packet%), которая возвращает адрес клиента от которого пришел пакет?... или адрес пакета в памяти?))?
RN_GetSystemAddressFromIndex(rakPeerInterface,inde x) - а эта наоборот получается... лана буду пробывать, т.с. эмпирическим путем понимать суть вопроса... :)
побывал...пробывал... но никак не получается получить на стороне клиента его индекс... блин... Хелп!!!

jimon 24.04.2008 00:30

Ответ: RakNet : большое время доставки пакетов
 
зачем на стороне клиента индекс ? O_o
клиент в клиент-серверной архитектуре имеет только одно подключение - к серверу
потому индекс подключения на клиенте - ноль ( 0 )
ты не можешь получить на стороне клиенте индекс подключения клиента на сервере

а на сервере получаешь адресс когда приходит пакет о подключении
потом из адресса получаешь индекс - и юзаешь его потом

перед посылкой пакета с сервера на клиент просто
переводишь индекс опять в адресс

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

GoodWin 24.04.2008 10:28

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

при подключении клиента на сервере создается игрок и ему присваивается ИД по индексу... с клиента на сервер отправляются пакеты с состоянием клавиш управления... на сервере происходит обновление игроков и отправляются на клиенты положения всех игроков... (в пакете кроме координат отсылается ИД игрока) и тут возникает проблема... не могу идентифицировать пакеты игрока по ИД на клиенте...
П.С. возникла идея... идентифицировать игрока по его имени, но тогда нужно проверять вводимое имя на незанятость....

jimon 24.04.2008 12:53

Ответ: RakNet : большое время доставки пакетов
 
GoodWin
1) клиент подключается к серверу

2) сервер ловит ID_NEW_INCOMING_CONNECTION
и создает у себя игрока, получает индекс сойденения
но у нас было только подключение на заданный порт
глупо сейчас считать это подключение нормальным
будем считать что подключение требует инициализации

3) клиент получает ID_CONNECTION_REQUEST_ACCEPTED
после этого клиент может узнать индекс подключению к серверу
после подключения отправляем пакет инициализации на сервер
обычно в пакете задают информацию о типе програмы клиента,
её версии и прочего, иногда даже информация о шифровании

в худшем случае клиент подключает ID_CONNECTION_ATTEMPT_FAILED
тогда нужно подключится заново, а сервер удалит старое
не инициализированое подключение по time-out (прошло много
времени, а пакет инициализации не пришол)

4) сервер получает пакет инициализации, из пакета получаем
индекс подключения и ищем такого игрока
записываем нужную информацию что пришла с пакетом
генерируем уникальный индекс для игрока (индекс подключения
лутче не использовать, черт его знает что случится сним)

и отправляем примерно такой же пакет инициализации игроку
в нем записываем id игрока, версию протокола и прочее

5) клиент получает пакет инициализации
и записывает из него свой id и прочую нужную информацию

после всего этого подключение считается завершенным
и клиент и сервер начинают свою работу
ps. именно так у меня всё работает в проекте :)


Часовой пояс GMT +4, время: 23:17.

vBulletin® Version 3.6.5.
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Перевод: zCarot