SDL UDP Example

Post your FreeBASIC source, examples, tips and tricks here. Please don’t post code without including an explanation.
Post Reply
Frank Dodd
Posts: 444
Joined: Mar 10, 2006 19:22

SDL UDP Example

Post by Frank Dodd »

Here is a small utility that I used to test some embedded code running on a remote unit, it demonstrates a simple use of SDL Net for UDP. This is my first (hopefully not my last) post here while having lots of fun with FreeBasic. I am particularly impressed by the fast compact appearance of the code in the GDB disassembly. Great forum guys I wish you lots of fun.

Code: Select all

'' ----------------------------------------------------------------------------
'' UDP Packet test for Network variables
'' Version 0.1
'' Author F.Dodd March 2006
'' FreeBasic v0.15 (www.freebasic.net/)
'' SDL Simple DirectMedia Layer v1.2 (www.libsdl.org/)
''
'' Thanks and acknowledgement to many members of the FreeBasic forums for
'' helpfull postings and code snippets to learn and crib from
''
'' ----------------------------------------------------------------------------

' Library includes ------------------------------------------------------------
' SDL Library for Networking support. Requires SDL.dll SDL_Net.dll
'$include: "SDL/SDL_net.bi"

' Structured type declarations ------------------------------------------------
' a network variables message
Type netvarmessage
	uifunction As Uinteger  ' what this message is to do
    uiindex As Uinteger     ' the index of the record being addressed
    uivalue As Uinteger     ' the value of the record being addressed
End Type

' Constant value declarations -------------------------------------------------
Const NET_VAR_WRITE = 0     ' function code for writing a variable value
Const NET_VAR_ACK = 1       ' function code for acknowledging a message
Const NET_VAR_PORT = 41003  ' the sockets port used for network variable comms

' Subroutine and Function declarations ----------------------------------------
' Swapping Little to Big endianess or visa-versa of a 32bit unsigned value
Declare Function SwapEndian( uiValue As Uinteger )
' writing a UDP packet containing a network variable write message
Declare Sub NetVarWrite( index As Uinteger, value As Uinteger )
' writing a UDP packet containing a network variable acknowledgement
Declare Sub NetVarAck()
' Handle a received network variable message
Declare Sub HandleNetVarMessage(silentsignal)
' Display a banner with some instructions
Declare Sub PrintHelp()

' Global variable declarations ------------------------------------------------
' these variables are shared across all subroutines and functions
Dim Shared As UDPsocket data_socket     ' the socket for UDP transmissions
Dim Shared As UDPpacket packet          ' buffer for UDP packet sends and receives
Dim Shared As netvarmessage data_buffer ' buffer for UDP packet data
Dim Shared As String address            ' string containing the network address


' -----------------------------------------------------------------------------
''
'' main() function
''
Dim As IPaddress iaddress               ' numerical host address and port
Dim As UInteger uiIndex = 0             ' a variable index
Dim As UInteger uiValue = 0             ' a variable value

' initialise the SDL network library
If SDLNet_Init() = 0 Then
    ' ask the user for host address
    Line Input "Please enter the host address (<Enter> for 192.168.0.65): ";address
    
    ' if the user entered a blank address
    If address = "" Then
        ' set the address to the default
        address = "192.168.0.65"
    End If
    
    ' resolve the host address for the specified address
    SDLNet_ResolveHost( @iaddress, Strptr(address), NET_VAR_PORT)
    
    ' open the socket on the network variable port
    data_socket = SDLNet_UDP_Open( NET_VAR_PORT )
    
    ' if the socket was successfully opened
    If Not data_socket = 1 Then
        
        ' bind the socket to the resolved host using the first available channel
        packet.channel = SDLNet_UDP_Bind( data_socket, -1, @iaddress )
        
        ' if the socket was successfully bound
        If Not packet.channel = -1 Then
            'display the help script
            PrintHelp
            
            ' a network variables udp packet always contains 12 bytes of data
            ' point the packet at our data buffer and specify the size of the
            ' buffer
            packet.Data = CAST( Zstring Ptr, @data_buffer )
            packet.Len = 12
            packet.maxlen = 12
            
            ' automatic acknowledgements are not silenced
            silentsignal = 0
            ' the exit signal is not raised
            exitsignal = 0

            ' inform the user that we are wait for a udp data packet
            Print "Listening for a packet ..."

            ' repeat until the exit signal is raised
            While exitsignal = 0
                ' handle incomming network messages ...........................
                
                ' check if there is a packet waiting
                sizerecv = SDLNet_UDP_Recv( data_socket, @packet)

                ' if data was received
                If sizerecv = 1 Then
                    ' process the received data
                    HandleNetVarMessage(silentsignal)

                    ' inform the user that we are wait for a udp data packet
                    Print "Press C to reset. Listening for a packet ..."
                End if

                ' handle user input ...........................................
                ' check if a key was pressed
                a$ = Inkey$

                ' arbitrate based on the pressed key
                Select Case a$
                Case "s","S"
                    ' user has asked to toggle acknowledment mode 
                    ' if we are not silent
                    If silentsignal = 0 Then 
                        ' switch into silent mode
                        Print "Silencing Replies"
                        silentsignal = 1
                    Else
                        ' we were in silent mode
                        ' switch into automatic acknowledgement mode
                        Print "Allowing Replies"
                        silentsignal = 0
                    End If
                    
                Case "w","W"
                    ' get the index and value
                    Line Input "Variable Number ";A$
                    Line Input "Variable Value  ";B$
                    uiIndex = Val(A$)
                    uiValue = Val(B$)

                    ' write the network variable
                    NetVarWrite( uiIndex, uiValue )
                    
                Case "r","R"
                    ' increment the value
                    uiValue += 1

                    ' resend the network variable
                    NetVarWrite( uiIndex, uiValue )
                    
                Case "a","A"
                    ' manually transmit an acknowledgement (this should
                    ' cause an unexpected ack error at the host)
                    NetVarAck
                    
                Case "c","C"
                    ' reset the display
                    Cls
                    PrintHelp
                    
                Case Else
                    ' handle non specific keys
                    ' If an unrecognised key is pressed its a signal to end
                    If Not a$ = "" Then
                        ' signal that the application is to exit
                        exitsignal = 1
                    End If
                    
                End Select
            Wend
        Else
            Print "Unable to bind socket"
        End If
        
        SDLNet_UDP_Close(data_socket)
    Else
        Print "Unable to open a socket on port ";NET_VAR_PORT
    End If
    
    SDLNet_Quit()
Else
    Print "SDL Library could not be initialised"
End If


' Subroutine and Function declarations ----------------------------------------

'' ............................................................................
'' Function to change the endianess of the data in the transmission
''
Function SwapEndian( uiValue As Uinteger )
    
    Dim uiConverted As Uinteger
    
	uiConverted = ( uiValue And &hFF ) Shl 24
	uiConverted += ( uiValue And &hFF00 ) Shl 8
	uiConverted += ( uiValue And &hFF0000 ) Shr 8
	uiConverted += ( uiValue And &hFF000000 ) Shr 24
    
	SwapEndian = uiConverted
    
End Function

'' ............................................................................
'' Subroutine to send a UDP packet that writes a network variable
''
Sub NetVarWrite( index As Uinteger, value As Uinteger )
    ' Format the network variable write data
    data_buffer.uifunction = 0
    data_buffer.uiindex = SwapEndian(index)
    data_buffer.uivalue = SwapEndian(value)
    
    ' send out an acknowledgement
    Print "Writing network variable ";index;" with ";value
    sizesent=SDLNet_UDP_Send(data_socket, packet.channel, @packet)
    
    ' display a message to the user if an error occurs
    If sizesent < 1 Then
        Print "Unable to send data correctly"
        
    End If
End Sub

'' ............................................................................
'' Subroutine to send a UDP packet that acknowledges a network variable write
''
Sub NetVarAck()
    ' Reply with an ACK
    data_buffer.uifunction = &h01000000
    
    ' send out an acknowledgement
    Print "Sending an acknowledgement"
    sizesent=SDLNet_UDP_Send(data_socket, packet.channel, @packet)
    
    ' display a message to the user if an error occurs
    If sizesent < 1 Then
        Print "Unable to send data correctly"
        
    End If
End Sub

'' ............................................................................
'' Handle a received network variable message
''
Sub HandleNetVarMessage(silentsignal)
    ' display the recieved packet
    Print Time$;": Received( Func:";SwapEndian(data_buffer.uiFunction);
    Print " Index:";SwapEndian(data_buffer.uiindex);
    Print " Value:";SwapEndian(data_buffer.uivalue);" )"
    
    ' if automatic acknowledgements are not silenced and 
    If silentsignal = 0 Then
        
        ' if the function code indicates we received a write
        If data_buffer.uifunction = 0 Then
            NetVarAck
        End If
        
    End If
    
    ' insert a blank line to format the display
    Print ""
End Sub

'' ............................................................................
'' Display a banner with some instructions
''
Sub PrintHelp()
    ' reset the display
    Cls
    ' display instructions
    Print "UDP Network Variable Test Software v0.1 talking to ";address
    Print
    Print "Press C to clear the display and reprint this message"
    Print "Press S to toggle automatic acknowledgments on and off"
    Print "Press A to manually transmit an acknowledgement"
    Print "Press W to manually send a test write message"
    Print "Press R to increment the value in and resend the test message"
    Print "Press any other key to exit"
    Print
    
End Sub

TbbW
Posts: 348
Joined: Aug 19, 2005 10:08
Contact:

Post by TbbW »

cool man :)
iwe been looking for udp examples but none seemed interested in making one.
thumbs up man! :)
Post Reply