UDP based lossless (optional) network engine. I'd appreciate if you could test it.
About server:
Every stream has it's own UDP port. First, client connects to server and then server will automatically redirect it to a new port.
I tested 22'000 packets in a row and it had no errors.
Functions:
Source:
Example:
About server:
Every stream has it's own UDP port. First, client connects to server and then server will automatically redirect it to a new port.
I tested 22'000 packets in a row and it had no errors.
Functions:
server% = CreateUDPServer%([port%]) stream% = AcceptUDPStream%(server%) stream% = OpenUDPStream%(ip$, port%, [localport%]) inip_from% = ReceiveUDPMsg%(stream%) - 0 if no message has arrived result% = WriteUDPByte%(stream%, value%) result% = WriteUDPBytes%(bank%, stream%, offset%, count%) result% = WriteUDPLine%(stream%, txt$) result% = WriteUDPInt%(stream%, value%) result% = WriteUDPString%(stream%, txt$) value% = ReadUDPByte%(stream%) value% = ReadUDPBytes%(bank%, stream%, offset%, count%) value% = ReadUDPLine$(stream%) value% = ReadUDPInt%(stream%) value% = ReadUDPString$(stream%) remote_port% = UDPPort%(stream%) remote_intip% = UDPIP%(stream%) byte_count% = UDPReadAvail%(stream%) RemoveUDPStream%(stream%)
Source:
Const UDPResponseDelay% = 2000, UDPRetries% = 5, LossLessUDP% = True Function CreateUDPServer%(port% = 0) Local server% = CreateUDPStream(port%), bank% If server% bank% = CreateBank(4 * 3 + 1) PokeInt bank%, 0 * 4, server% PokeInt bank%, 1 * 4, UDPStreamIP(server%) PokeInt bank%, 2 * 4, UDPStreamPort(server%) PokeByte bank%, 3 * 4, 1 Return bank% EndIf End Function Function AcceptUDPStream%(bank%) Local accepted% Local server% = PeekInt(bank%, 0 * 4) Local ip% = PeekInt(bank%, 1 * 4) Local port% = PeekInt(bank%, 2 * 4) Local from% = RecvUDPMsg(server%) If from% clientip% = UDPMsgIP(server%) clientport% = UDPMsgPort(server%) value% = ReadInt(server%) If value% => 12345 And value% =< 23456 Then ; Create stream bank bank% = CreateBank(4 * 3 + 1) accepted% = CreateUDPStream() PokeInt bank%, 0, accepted% PokeInt bank%, 4, clientip% PokeInt bank%, 8, clientport% PokeByte bank%, 12, 0 WriteInt accepted%, UDPStreamPort(accepted%) SendUDPMsg accepted%, clientip%, clientport% Return bank% Else FreeBank bank% CloseUDPStream accepted% Return False EndIf EndIf End Function Function OpenUDPStream%(ip$, port%, localport% = 0) Local stream% = CreateUDPStream(localport%) Local bank% = CreateBank(4 * 3 + 1) PokeInt bank%, 0, stream% PokeInt bank%, 4, IntIP(ip$) PokeInt bank%, 8, port% PokeByte bank%, 12, 1 validation% = Rand(12345, 23456) WriteInt stream%, validation% SendUDPMsg stream%, PeekInt(bank%, 4), PeekInt(bank%, 8) For i = 1 To UDPRetries% tim% = MilliSecs() Repeat from% = RecvUDPMsg(stream%) Until from% Or MilliSecs() - tim% > UDPResponseDelay% If from% value% = ReadInt(stream%) PokeInt bank%, 8, value% Return bank% EndIf Next ; Failed FreeBank bank% CloseUDPStream stream% Return False End Function Function ReceiveUDPMsg%(bank%) Local stream% = PeekInt(bank%, 0) Local ip% = PeekInt(bank%, 4) Local port% = PeekInt(bank%, 8) Local msgindex% = PeekByte(bank%, 12) from% = RecvUDPMsg(stream%) If from% If UDPMsgIP(stream%) = ip% And UDPMsgPort(stream%) = port% index% = ReadByte(stream%) If LossLessUDP% If Not index% = msgindex% ; Response to message PokeByte bank%, 12, index% WriteByte stream%, index% SendUDPMsg stream%, ip%, port% Return from% Else DebugLog "Invalid message index!" ; Message already received WriteByte stream%, index% SendUDPMsg stream%, ip%, port% Return False EndIf Else Return from% EndIf EndIf EndIf End Function Function WriteUDPByte%(bank%, value%) Local stream% = PeekInt(bank%, 0) Local ip% = PeekInt(bank%, 4) Local port% = PeekInt(bank%, 8) Local msgindex% = PeekByte(bank%, 12) For i = 1 To UDPRetries% ; Send message WriteByte stream%, msgindex% WriteByte stream%, value% SendUDPMsg stream%, ip%, port% If WaitUDPResponse(bank%) Then Return True Next End Function Function ReadUDPByte%(bank%) Local stream% = PeekInt(bank%, 0) Local ip% = PeekInt(bank%, 4) Local port% = PeekInt(bank%, 8) Local msgindex% = PeekByte(bank%, 12) Return ReadByte(stream%) End Function Function WriteUDPBytes%(from%, bank%, offset%, count%) Local stream% = PeekInt(bank%, 0) Local ip% = PeekInt(bank%, 4) Local port% = PeekInt(bank%, 8) Local msgindex% = PeekByte(bank%, 12) For i = 1 To UDPRetries% ; Send message WriteByte stream%, msgindex% WriteBytes from%, stream%, offset%, count% SendUDPMsg stream%, ip%, port% If WaitUDPResponse(bank%) Then Return True Next End Function Function ReadUDPBytes%(from%, bank%, offset%, count%) Local stream% = PeekInt(bank%, 0) Local ip% = PeekInt(bank%, 4) Local port% = PeekInt(bank%, 8) Local msgindex% = PeekByte(bank%, 12) Return ReadBytes(from%, stream%, offset%, count%) End Function Function WriteUDPInt%(bank%, value%) Local stream% = PeekInt(bank%, 0) Local ip% = PeekInt(bank%, 4) Local port% = PeekInt(bank%, 8) Local msgindex% = PeekByte(bank%, 12) For i = 1 To UDPRetries% ; Send message WriteByte stream%, msgindex% WriteInt stream%, value% SendUDPMsg stream%, ip%, port% If WaitUDPResponse(bank%) Then Return True Next End Function Function ReadUDPInt%(bank%) Local stream% = PeekInt(bank%, 0) Local ip% = PeekInt(bank%, 4) Local port% = PeekInt(bank%, 8) Local msgindex% = PeekByte(bank%, 12) Return ReadInt(stream%) End Function Function WriteUDPString%(bank%, txt$) Local stream% = PeekInt(bank%, 0) Local ip% = PeekInt(bank%, 4) Local port% = PeekInt(bank%, 8) Local msgindex% = PeekByte(bank%, 12) For i = 1 To UDPRetries% ; Send message WriteByte stream%, msgindex% WriteString stream%, txt$ SendUDPMsg stream%, ip%, port% If WaitUDPResponse(bank%) Then Return True Next End Function Function ReadUDPString$(bank%) Local stream% = PeekInt(bank%, 0) Local ip% = PeekInt(bank%, 4) Local port% = PeekInt(bank%, 8) Local msgindex% = PeekByte(bank%, 12) Return ReadString(stream%) End Function Function WriteUDPLine%(bank%, txt$) Local stream% = PeekInt(bank%, 0) Local ip% = PeekInt(bank%, 4) Local port% = PeekInt(bank%, 8) Local msgindex% = PeekByte(bank%, 12) For i = 1 To UDPRetries% ; Send message WriteByte stream%, msgindex% WriteLine stream%, txt$ SendUDPMsg stream%, ip%, port% If WaitUDPResponse(bank%) Then Return True Next End Function Function ReadUDPLine$(bank%) Local stream% = PeekInt(bank%, 0) Local ip% = PeekInt(bank%, 4) Local port% = PeekInt(bank%, 8) Local msgindex% = PeekByte(bank%, 12) Return ReadLine(stream%) End Function Function UDPPort%(bank%) Return PeekInt(bank%, 2 * 4) End Function Function UDPIP%(bank%) Return PeekInt(bank%, 1 * 4) End Function Function UDPReadAvail%(bank%) Return ReadAvail(PeekInt(bank%, 0 * 4)) End Function Function RemoveUDPStream%(bank%) Local stream% = PeekInt(bank%, 0) Local ip% = PeekInt(bank%, 4) Local port% = PeekInt(bank%, 8) CloseUDPStream stream% FreeBank bank% End Function ; NON-USER COMMANDS -------------------------------------------------------------------------------- Function WaitUDPResponse%(bank%) Local stream% = PeekInt(bank%, 0) Local ip% = PeekInt(bank%, 4) Local port% = PeekInt(bank%, 8) Local msgindex% = PeekByte(bank%, 12) If LossLessUDP% ; Wait for replay tim% = MilliSecs() Repeat from% = RecvUDPMsg(stream%) Until from% Or MilliSecs() - tim% > UDPResponseDelay% If from% If UDPMsgIP(stream%) = ip% And UDPMsgPort(stream%) = port% ; Message from same client index% = ReadByte(stream%) If index% = msgindex% If msgindex% < 250 Then PokeByte bank%, 12, msgindex% + 1 Else PokeByte bank%, 12, msgindex% - 250 Return True EndIf EndIf EndIf Else Return True EndIf End Function Function IntIP(ip$) Local a = UDPSector$(ip$, ".", 0) Local b = UDPSector$(ip$, ".", 1) Local c = UDPSector$(ip$, ".", 2) Local d = UDPSector$(ip$, ".", 3) Return (a Shl 24) + (b Shl 16) + (c Shl 8) + d End Function Function UDPSector$(txt$, separator$, sector%, toend% = False) Local result$ = "", occ For i = 1 To Len(txt$) If Mid$(txt$, i, 1) = separator$ occ = occ + 1 If toend% And occ% > sector% Then result$ = result$ + Mid$(txt$, i, 1) Else If occ => sector Then result$ = result$ + Mid$(txt$, i, 1) EndIf If Not toend% Then If occ > sector Then Exit Next Return result$ End Function Function UDPSectors%(txt$, needle$) occ% = 0 For i = 1 To Len(txt$) Step 1 If Instr(txt$, needle$, i) occ% = occ% + 1 i = Instr(txt$, needle$, i) Else Exit EndIf Next Return occ% End Function
Example:
; ------------Server-------------- Include "udp.bb" Print "Creating UDP server..." server% = CreateUDPServer(2010) If server% Print "Waiting for client..." Repeat stream% = AcceptUDPStream(server%) Until stream% Print "Client (" + DottedIP(UDPIP(stream%)) + ":" + UDPPort(stream%) + ") connected!" Repeat If ReceiveUDPMsg%(stream%) avail% = UDPReadAvail(stream%) Print avail% + " bytes available!" value$ = ReadUDPLine$(stream%) Print "Message: " + value$ EndIf Forever Else Print "Failed to create server!" EndIf WaitKey ; ------------Client-------------- Include "udp.bb" Print "Connecting to server..." stream% = OpenUDPStream("127.0.0.1", 2010) If stream% Print "Received access to " + DottedIP(UDPIP(stream%)) + ":" + UDPPort(stream%) For i = 1 To 1000 msg$ = "Hello message #" + i + "!" If WriteUDPLine(stream%, msg$) Print "Message: " + msg$ EndIf Next Else Print "Failed!" EndIf WaitKey