I have written a basic network server code, which can receive and store messages into memory, and only release them for further processing once they are deemed to be fully received. Can you please take a look at this code and make comments as to it's reliability, possible sources of trouble or even stuff I'm doing which can be safely omitted. Thanks!
Code: Select all
; I'm assuming at this point that the server is already running - that much is easy.
#SERVER_RECEPTION_LENGTH = 1024 ; How many bytes to receive per round
#NETWORKMESSAGE_TIMEOUT = 5000 ; Timeout for non-finalised messages
#NETWORKMESSAGE_SEPARATOR = Chr(254) ; Separator character between messages.
Structure NetworkMessage ; Contains the received network messages.
Sender.l ; Holds the value returned by EventClient()
Content.s ; The actual content of the message
Finalised.b ; #True if the message is fully received, #False if more data is waiting.
Timeout.l ; When the message isn't yet Finalised, this will hold an ElapsedMilliseconds() timestamp. When a message hasn't been updated for #NETWORKMESSAGE_TIMEOUT milliseconds, it gets discarded.
EndStructure
Global NewList NetworkMessages.NetworkMessage()
Global *server_reception_buffer = AllocateMemory(#SERVER_RECEPTION_LENGTH)
Procedure Server_HandleNetworkEvents()
Protected ServerEvent = NetworkServerEvent(), EventClient, messagematch.b, server_reception_length.w
; Delete old, non-finalised network messages.
ForEach NetworkMessages()
If NetworkMessages()\Finalised = #False And ElapsedMilliseconds()-NetworkMessages()\Timeout > #NETWORKMESSAGE_TIMEOUT
DeleteElement(NetworkMessages())
EndIf
Next
If ServerEvent
EventClient = EventClient()
Select ServerEvent
Case #PB_NetworkEvent_Connect
; No code yet...
Case #PB_NetworkEvent_Data
; Check if a non-finalised message by this Client is already present.
messagematch = 0
ForEach NetworkMessages()
If NetworkMessages()\Sender = EventClient And NetworkMessages()\Finalised = #False
messagematch = #True
NetworkMessages()\Timeout = ElapsedMilliseconds()
Break
EndIf
Next
If messagematch = 0 ; If no non-finalised message by this Client is present, create a new one.
AddElement(NetworkMessages())
NetworkMessages()\Sender = EventClient
NetworkMessages()\Timeout = ElapsedMilliseconds()
EndIf
Repeat ; Keep looping until all data has been received
server_reception_length = ReceiveNetworkData(EventClient, *server_reception_buffer, #SERVER_RECEPTION_LENGTH)
If server_reception_length > 0
NetworkMessages()\Content = NetworkMessages()\Content + PeekS(*server_reception_buffer, server_reception_length)
If Right(NetworkMessages()\Content, 1) = #NETWORKMESSAGE_SEPARATOR ; If the separator has been found at the end of the message, finalise the message.
NetworkMessages()\Finalised = #True
NetworkMessages()\Content = RTrim(NetworkMessages()\Content, #NETWORKMESSAGE_SEPARATOR)
EndIf
EndIf
If server_reception_length = -1 ; Seems something went wrong...
LogMessage("Error in network message reception.", #LOGLEVEL_ERROR)
EndIf
Until Not server_reception_length = #SERVER_RECEPTION_LENGTH
Case #PB_NetworkEvent_Disconnect
; No code yet...
EndSelect
EndIf
EndProcedure
If I keep querying ReceiveNetworkData(), can it be said with absolute certainty that I will only receive data sent by the client previously identified with EventClient(), or is it possible, that every call to RecieveNetworkData() may give me data sent by a different client?!
Sorry for making something seemingly so easy so difficult, but I really want my reception stack to be reliable and as flawless as possible. A lot is at stake...