Any good cross-platform bmx libraries out there?
Network library with guaranteed UDP?
BlitzMax Forums/BlitzMax Programming/Network library with guaranteed UDP? gnet or BNetEx
I can't seem to find BNetEx. All links I can find are dead?
I don't think gnet has garanteed UDP, or ??? (as it is based on ENET, maybe it's implemented ?)
BNetEx
Bnet only supports unreliable udp. You would need to code an ack type system for safe udp.
Checked out enet. It has guaranteed UDP and looks pretty cool actually. With bandwidth control and stuff.
I'll look into it some more and get back to you :)
I'll look into it some more and get back to you :)
isnt the point of UDP is that its not guaranteed? just fire and forget and hope it gets there.
Yes and no.
The main reason to use UDP is that you can enable guaranteed only on important messages but not on unimportant stuff.
That way you can have high frequency where needed but as well guaranteed receive where needed (login message for example)
The main reason to use UDP is that you can enable guaranteed only on important messages but not on unimportant stuff.
That way you can have high frequency where needed but as well guaranteed receive where needed (login message for example)
I wrapped ENet in a simple class in about 10 mins and it works like a charm :)
Enet is ALREADY wrapped with BlitzMax !!! This was done by Mark Sibly 6 months ago, and used in gnet. However, I am not sure if it was 100% wrapped??
GNet is not what I was looking for ;)
It's not a 100% wrapped, the ping functions among others are missing.
I might have a go at it later, but for now my own wrapper is just what I need :)
It's not a 100% wrapped, the ping functions among others are missing.
I might have a go at it later, but for now my own wrapper is just what I need :)
are you going to post it for us?
Never done anything multiplayer, but Wave's TNet:
http://www.truplo.com/TNet/
Dunno about guaranteed UDP, it says "reliable". :)
http://www.truplo.com/TNet/
Dunno about guaranteed UDP, it says "reliable". :)
It's not reliable.
Here's my wrapper.
You'll still need the occasional ENet function tho.
So you need to call update and you get callbacks when stuff happens.
This might come in handy too:
Send with
The peer is found in the event structure you get on the callbacks.
For futher questions, don't hesitate to ask :)
Here's my wrapper.
You'll still need the occasional ENet function tho.
SuperStrict ' ENet wrapper on top of ENet by Odin Jensen (Some borrowing from gnet ;) ' Inherit and override On* funcs to get it off the road :) Type TENetModule ' ENet host Field _enetHost:Byte Ptr ' Events list Field _enetEvents:TList=New TList ' Current unique ID Field _uniqueID:Long = 0 ' Start server at given port Method Host%(port%, maxClients% = 32, incomingLimit% = 0, outgoingLimit% = 0) ' Create server Local addr:Byte Ptr=enet_address_create(ENET_HOST_ANY, port) _enetHost=enet_host_create(addr, maxClients, incomingLimit, outgoingLimit) enet_address_destroy(addr) ' Failed? If (Not _enetHost) Return False End If ' All went well Return True End Method ' Connect to server at given address/port Method Connect%(address:String, port%, timeout%=10000, incomingLimit% = 0, outgoingLimit% = 0) ' Create client host _enetHost=enet_host_create(Null, 32, incomingLimit, outgoingLimit) ' Failed? If (Not _enetHost) Return False End If ' Attempt connection Local addr:Byte Ptr=enet_address_create(HostIp(address),port) Local peer:Byte Ptr=enet_host_connect(_enetHost,addr,1) enet_address_destroy(addr) If (Not peer) Return False End If timeout:+MilliSecs() While (timeout-MilliSecs() > 0) UpdateENetEvents(0) For Local ev:ENetEvent=EachIn _enetEvents If (ev.event=ENET_EVENT_TYPE_CONNECT And ev.peer=peer) OnConnect(ev) _enetEvents.Remove(ev) Return True EndIf Next Wend ' No go bub Return False End Method ' Disconnect Method Disconnect(peer:Byte Ptr) enet_peer_disconnect(peer) End Method ' Get unique ID Method GetUniqueID%() _uniqueID:+1 Return _uniqueID End Method ' Send packet Method Send%(peer:Byte Ptr, data:Byte Ptr, dataLen%, reliable%=True) ' Which flag? Local flag% = ENET_PACKET_FLAG_RELIABLE ' Unrealiable packet requested? If (Not reliable) flag = 0 ' This correct? Need to check ENet source one day :) End If ' Build packet 'Local buf:Byte Ptr=MemAlloc(dataLen) 'MemCopy(buf, data, dataLen) Local packet:Byte Ptr=enet_packet_create(data, dataLen, flag) 'MemFree(buf) ' Attempt send If (enet_peer_send(peer, 0, packet) < 0) Return False End If ' All went well Return True End Method ' Shutdown Method Shutdown() ' Destroy ENet stuff enet_host_flush(_enetHost) enet_host_destroy(_enetHost) End Method ' Update ENet events Method UpdateENetEvents(timeout%=0) ' Loop as long as there's messages waiting in line Repeat Local ev:ENetEvent=New ENetEvent If (Not enet_host_service(_enetHost,ev,timeout)) Return _enetEvents.AddLast(ev) Forever End Method ' Update Method Update(timeout%=0) ' Get messages UpdateENetEvents(timeout) ' Loop until no more packets left Repeat ' Time to leave eternal loop? If (_enetEvents.IsEmpty()) Return ' Get next event Local ev:ENetEvent=ENetEvent(_enetEvents.RemoveFirst()) ' Check out event type Select(ev.event) Case ENET_EVENT_TYPE_CONNECT OnConnect(ev) Case ENET_EVENT_TYPE_DISCONNECT OnDisconnect(ev) Case ENET_EVENT_TYPE_RECEIVE OnDataRecieved(ev) End Select Forever End Method ' Called on new connection Method OnConnect(ev:ENetEvent) Abstract ' Called on disconnect Method OnDisconnect(ev:ENetEvent) Abstract ' Called when data recieved (Remember to enet_packet_destroy() packet, when you're done!) Method OnDataRecieved(ev:ENetEvent) Abstract End Type
So you need to call update and you get callbacks when stuff happens.
This might come in handy too:
SuperStrict ' Network packet for easier handling of banks (C)2006 Odin Jensen Type TNetPacket Field bank:TBank Field curOffset%=0 ' Init packet Method Init(size%=512) Self.bank = CreateBank(size) End Method ' Rewind Method Rewind() curOffset = 0 End Method ' Bank to string Method BankToString:String(bank:TBank) Local ret:String = "" For Local i:Int = 0 To BankSize(bank)-1 ret:+Chr(PeekByte(bank, i)) Next Return ret End Method ' Create from ENet packet Method FromENetPacket(packet:Byte Ptr) Local buf:Byte Ptr=enet_packet_data( packet ) Local size%=enet_packet_size( packet ) ResizeBank(Self.Bank, size) MemCopy(Lock(), buf, size) Unlock() Rewind() End Method ' Get offset Method GetOffset%() Return curOffset End Method ' Get size Method GetSize%() Return BankSize(bank) End Method ' Lock it Method Lock:Byte Ptr() Return LockBank(bank) End Method ' Unlock Method Unlock() UnlockBank(bank) End Method ' Write integer Method WriteInt(value%) If (curOffset+4 >= GetSize()) ResizeBank(bank, GetSize()+8) DebugLog("Bank resize!") End If PokeInt(bank, curOffset, value) curOffset:+4 End Method ' Write string Method WriteString(value:String) Self.WriteInt(value.length) If (curOffset+value.length >= GetSize()) ResizeBank(bank, GetSize()+(value.length*2)) DebugLog("Bank resize!") End If For Local i:Int = 0 To value.length PokeByte(bank, curOffset+i, value[i]) Next curOffset:+value.length End Method ' Write float Method WriteFloat(value:Float) If (curOffset+4 >= GetSize()) ResizeBank(bank, GetSize()+8) DebugLog("Bank resize!") End If PokeFloat(bank, curOffset, value) curOffset:+4 'DebugLog("NetPacket: Wrote float (" + value + ")") End Method ' Read integer Method ReadInt%() Local ret%=PeekInt(bank, curOffset) curOffset:+4 Return ret End Method ' Read string Method ReadString:String() Local size% = Self.ReadInt() Local ret:String = "" For Local i:Int = 0 To size-1 ret:+Chr(PeekByte(bank, curOffset +i)) Next curOffset:+size Return ret End Method ' Read float Method ReadFloat#() Local ret:Float = PeekFloat(bank, curOffset) curOffset:+4 'DebugLog("NetPacket: Read float (" + ret + ")") Return ret End Method End Type
Send with
' Send it good SendPacket.Rewind() SendPacket.WriteInt(SOME_PACKET_ID) SendPacket.WriteString("Hello!") Send(player.peer, SendPacket.Lock(), SendPacket.GetOffset()) SendPacket.Unlock()
The peer is found in the event structure you get on the callbacks.
For futher questions, don't hesitate to ask :)
oops!
I'd wondered about the "reliable packet" option in GNet ever since it was mentioned that it uses ENet/UDP, so thanks for your ENet wrapper/GNet extender, ozak. I've been a fan of UDP's optional-reliability nature ever since using Surreal's BlitzPlay with Blitz3D.
Unless you're writting an application that really ought to use TCP, you don't really need reliable UDP. Sequential is usually good enough.