[Gambas-user] gb3: using string as stream for sequential write operations of arbitrary datatypes

Kevin Fishburne kevinfishburne at ...1887...
Tue Aug 30 07:52:59 CEST 2011


Crap, I accidentally sent this to the man himself instead of the mailing 
list. Sorry about that Benoît.

I'm implementing client-server network transaction histories so that 
transactions which are sent but aren't answered by an acknowledgment 
(dropped/lost) are resent. I don't want to have to recreate the 
transaction payloads however, but simply resend a copy of what was 
originally sent. Here's an example of what I'm doing (edited and 
condensed for legibility):

Public Sub UDP_Write_120(ip As String, port As Integer, id As Byte, 
player As Short, worldx As Single, worldy As Single)

   ' Send "players data update, world coordinates, one player" 
transaction to specified IP address and port over UDP.

   ' Define target's IP address and port.
   udp.TargetHost = ip
   udp.TargetPort = port

   ' Send transaction.
   udp.Begin
     Write #udp, id As Byte
     Write #udp, 120 As Byte
     Write #udp, player As Short
     Write #udp, worldx As Single
     Write #udp, worldy As Single
   udp.Send

   ' Add to transaction history.
   UDP_Write_Finish(ip, port, id, 120)

End

The recipient will receive a string (data) which I break down into 
separate variables using the code:

   ' Parse UDP data and assign to variables.
   id = Read #udp As Byte
   type = Read #udp As Byte
   If Eof(udp) = False Then data = Read #udp, Lof(udp)

   ' Parse UDP data and add to client's server transaction queue.
   Client.QueueIn[id].Type = type    ' Type.
   Client.QueueIn[id].Data = data    ' Data

   ' New transaction found, assign its data to variables.
   tstype = QueueIn[tspos].Type  ' Type.
   tsdata = QueueIn[tspos].Data  ' Data.

   ' Update another player's position from the transaction queue.
   pposition[Short@(Convert.Reverse(Mid$(tsdata, 1, 2))), 0] = 
Single@(Convert.Reverse(Mid$(tsdata, 3, 4)))
   pposition[Short@(Convert.Reverse(Mid$(tsdata, 1, 2))), 1] = 
Single@(Convert.Reverse(Mid$(tsdata, 7, 4)))

All this works extremely well. The problem is when I try to store the 
payload (player, worldx, worldy) for the outgoing transaction in the 
transaction history. When writing variables to the network socket, a 
string containing the variables is received by the recipient which I can 
parse. I need to add that string to the transaction history of the 
sender. The "UDP_Write_Finish()" procedure mentioned looks like this:

Public Sub UDP_Write_Finish(ip As String, port As Integer, id As Byte, 
type As Byte)

   ' Perform post-write tasks. Called after a transaction has been sent.

   ' General declarations.
   Dim Player As Short

   ' Determine client/server mode.
   If mode = "server" Then
     ' Look up player number.
     Player = Server.Player_Find_IP(ip)
     ' Add transaction to server's outgoing transaction queue.
     Server.QueueOut[Player, id].Acknowledged = False
     Server.QueueOut[Player, id].Timestamp = Timer
     Server.QueueOut[Player, id].Type = type
     Server.QueueOut[Player, id].Data = ???
     ' Increment the server transaction ID for the client.
     Server.Increment_ID(Player)
     ' Display debug info.
     Console.Say("Sent to client " & ip & ", Port: " & port & ", ID: " & 
id & ", Type: " & type)
   Else
     ' Add transaction to client's outgoing transaction queue.
     Client.QueueOut[id].Acknowledged = False
     Client.QueueOut[id].Timestamp = Timer
     Client.QueueOut[id].Type = type
     Client.QueueOut[id].Data = ???
     ' Increment the client transaction ID.
     Client.Increment_ID
     ' Display debug info.
     Console.Say("Sent to server " & ip & ", Port: " & port & ", ID: " & 
id & ", Type: " & type)
   Endif

End

When a transaction isn't received and I need to resend it, I'd like to 
be able to refer to the transaction history and resend the data 
(QueueOut[id].Data) without having to recalculate it, especially since 
the data may have changed during the timeout period. I don't see any way 
to store a completely arbitrary set of datatypes as a single structure 
property however. I could write them to a file, then read the file into 
a string and load it into a property of the array of structures, but 
that's just crazy.

As you may remember the converse of the [datatype]@ functions solved 
this problem but were removed from gb3. If any other solution is 
available I'd like to hear about it. The subject line of the email is 
one suggestion, though I don't know if it's possible. If it is possible 
then I could create a string from arbitrary variables, send the string 
via UDP and archive it in the transaction history. Any insight is 
appreciated, as always.

-- 
Kevin Fishburne
Eight Virtues
www: http://sales.eightvirtues.com
e-mail: sales at ...1887...
phone: (770) 853-6271





More information about the User mailing list