Home Forums Support Simple Broadcast and Receive of Raw Bytes using UDP

  • This topic has 7 replies, 2 voices, and was last updated 8 years ago by Anonymous.
Viewing 8 posts - 1 through 8 (of 8 total)
  • Author
    Posts
  • #2676
    Anonymous
    Inactive

    Hello Network Comms,

    Very nice to see how this SDK has moved along. I looked at it last year(?) when it required packet header and wouldn’t let you send/receive raw bytes from third party devices – i.e. devices not running NetworkComms.

    I am using it now for TCP server section of app and it works very nicely. Thank you, however…..

    How do I do the following:

    1. Set up a very simple continuous UDP broadcast sending byte[] to specific port. This packet is being listened for from various third party devices on a specific port.

    2. Listen for a UDP packet (again byte[]) being sent from a third party device. This packet is being sent to a specific port on our device running NetworkComms

    Firstly, I have gone through all of the forums, but it seems quite full of obsolete information for the v3.0 release. Secondly, the UDP Broadcast and TCP/UDP Connection samples only show example on how to setup with managed and not unmanaged input/output.

    Am I missing something quite simple here. I have been going in circles for better part of a day here.

    Thanks in advance for help

    #2678
    Anonymous
    Inactive

    Heya Don,

    Many kind thanks for your support. We are glad that you would like to make use of the unmanaged connection support added in version 3.0. The API documentation for these latest version 3.0 features is a little sparse at the moment. The following code example is all you should need to send and receive unmanaged UDP broadcasts:

    //Ensure we use the null serializer for unmanaged connections
    SendReceiveOptions options = new SendReceiveOptions<NullSerializer>();
    
    //Setup listening for incoming unmanaged UDP broadcasts
    UDPConnectionListener listener = new UDPConnectionListener(options, ApplicationLayerProtocolStatus.Disabled, UDPOptions.None);
    Connection.StartListening(listener, new IPEndPoint(IPAddress.Any, 10000));
    
    //Add a packet handler for unmanaged connections
    NetworkComms.AppendGlobalIncomingUnmanagedPacketHandler((packetHeader, connection, incomingBytes) => {
        Console.WriteLine("Received {0} bytes from {1}", incomingBytes.Length, connection.ConnectionInfo.RemoteEndPoint);
    });
    
    //Generate some test data to broadcast
    byte[] dataToSend = new byte[] { 1, 2,3, 4 };
    
    //Create an unmanaged packet manually and broadcast the test data
    //In future this part of the API could potentially be improved to make it clearer
    using(Packet sendPacket = new Packet("Unmanaged", dataToSend, options))
        UDPConnection.SendObject<byte[]>(sendPacket, new IPEndPoint(IPAddress.Broadcast, 10000), options, ApplicationLayerProtocolStatus.Disabled);
    
    Console.WriteLine("Client done!");
    Console.ReadKey();

    If you have any questions on the above please feel free to post back.
    Regards,
    Marc

    #2705
    Anonymous
    Inactive

    Hi Marc – Thanks for reply. Just getting back to this now and can send/receive unmanaged UDP packets using this code snippet. That’s great, but now I have some housekeeping questions for UDP input.

    I’m not clear on open, close and reopening of connection with your code example.

    I create the udpListener with udpListener= UDPConnectionListener(…), and then start listening on a specific port with Connection.StartListening(udpListener, new IPEndPoint(IPAddress.Any, 10000)) and then append a packet handler routine. The listener is up and running and my third-party device can transmit raw bytes to this listener.

    That’s great, but now what about closing the connection and reopening? Currently, I remove the packet handler routine with udpListener.RemoveIncomingUnmanagedPacketHandler() and then stop listening with Connection.StopListening(udpListener).

    I can start listening on a different port, but if I try to start listening again on the same port, i.e. Connection.StartListening(udpListener, new IPEndPoint(IPAddress.Any, 10000)), I get an exception error as follows:

    An unhandled exception of type ‘NetworkCommsDotNet.ConnectionSetupException’ occurred in NetworkCommsDotNetComplete.dll

    Additional information: A UDP connection already exists with info [UDP-D-U] 0.0.0.0:10000 -> 0.0.0.0:0

    My question is:

    How do I start listening, stop listening and the start listening again – or better yet how do you close a UDPConnectionListener other than calling NetworkComms.Shutdown() ?

    It looks like there are ways to handle this when creating managed UDP connections with new ConnectionInfo(…) and UDPConnection.GetConnection(…) because you can call CloseConnection() etc… but you don’t have the same ability when create unmanaged UDP connections with new UDPConnectionListener(…)

    Everything seems fine if call NetworkComms.Shutdown() and then start it back up again, but I would rather not have to restart all network comms because needing to change input port for a single listener.

    Thanks in advance.

    #2706
    Anonymous
    Inactive

    Hey Don,

    Connections as you are thinking of them do not exist for UDP. At the heart of it you only ever send a packet and listen for packets. i.e There is nothing stopping you from sending a packet to a destination that is not listening.

    After you have stopped listening do you recreate the udp listener or attempt to reuse an existing one?

    Also it is a very odd use case to open/close/open the same listening port again, any chance you could give me some insight into what you are trying to achieve?

    Regards,
    Marc

    #2707
    Anonymous
    Inactive

    Yes, I agree with your view on UDP protocol. What we have are a bunch of PLCs broadcasting UDP packets of raw bytes to the App on specific ports. The PLCs will broadcast if App is not listening.

    Our problem occurs when we need to change the ports on which the App is listening. Here is the scenario where this will happen.

    App starts up and creates a series of UDP listeners which are listening for PLCs that are not very smart and simply broadcast UDP packets to a specific port. For example, udpListenerA is listening on port 11000 for PLCA and udpListenerB is listening on 11001 for PLCB. The packet handlers are unique for udpListenerA and udpListenerB – in other words, they “know” who is sending them data (based on port) and are able to parse the incoming bytes accordingly. It is not possible to make a generic common packet handler because looking at raw bytes with no unique internal header information.

    It appears that it is not possible to do the following:

    On startup…
    Get ports from App configuration.
    nPortPLCA= 11000;
    nPortPLCB= 11001;

    Connection.StartListening(udpListenerA, new IPEndPoint(IPAddress.Any, nPortPLCA)),
    Connection.StartListening(udpListenerB, new IPEndPoint(IPAddress.Any, nPortPLCB)),

    … operator sees that APP is getting garbage data from both PLCA or PLCB and realizes that the problem is that someone has set the ports wrong, PLCA is actually broadcasting on 11001 and PLCB is broadcasting on 11000, so wants to change them.

    if ( udpListenerA.IsListening )
    Connection.StopListening(udpListenerA);
    if ( udpListenerB.IsListening )
    Connection.StopListening(udpListenerB);

    Display configuration dialog that allows operator to change input ports, so now:
    nPortPLCA= 11001;
    nPortPLCB= 11000;
    Save to App configuration, and now start listening on the “new” ports.

    Connection.StartListening(udpListenerA, new IPEndPoint(IPAddress.Any, nPortPLCA)),
    Connection.StartListening(udpListenerB, new IPEndPoint(IPAddress.Any, nPortPLCB)),

    ….but can’t do this because get exception error if try to “reuse” port 11001 (nPortPLCA).

    As for recreating or reusing the listener. I have done both and get same error. Problem doesn’t seem to be with udpListener, but rather when calls Connection.StartListening( listener, <IP,port combo that has been used previously>);

    If the solution is that I need to tell the Operator that he needs to restart the App if changes the input ports, then so be it. I would rather not if I’m just missing something obvious….

    Thanks again.

    #2708
    Anonymous
    Inactive

    It sounds like a possible bug. If you could create a minimal test case that reproduces the problem and post it here I can take a look and hopefully propose a solution.

    Marc

    #2709
    Anonymous
    Inactive

    WPF App with 6 buttons will do the trick.

    2 buttons to Broadcast UDP to either Port 10000 or 20000

    Click=btnClick_TxTo10000
    Click=btnClick_TxTo20000

    and 4 buttons to create udp listener, stop listening and start listening on either 10000 or 20000

    Click=btnClick_CreateUDPListener
    Click=btnClick_StopListening
    Click=btnClick_ListenUDPOn10000
    Click=btnClick_ListenUDPOn20000

    In this situation, I am just reusing the UDPListener and not recreating. Same exception in either case though.

    
    <Window x:Class="TestNetworkComms.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="NetworkComms Test" Height="200" Width="712" Closing="Window_Closing">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="*"/>
                <RowDefinition Height="50"/>
            </Grid.RowDefinitions>
    
            <StackPanel Grid.Row="1" Orientation="Horizontal">
                <Button Content="Tx 10000" Margin="3" Width="80" Background="Orange" Click="btnClick_TxTo10000"/>
                <Button Content="Tx 20000" Margin="3" Width="80" Background="Orange" Click="btnClick_TxTo20000"/>
                <Button Content="UDP Input" Margin="3" Width="80" Background="DarkGreen" Click="btnClick_CreateUDPListener"/>
                <Button Content="UDP Input" Margin="3" Width="80" Background="DarkRed" Click="btnClick_StopListening"/>
                <Button Content="UDP Debug 1" Margin="3" Width="80" Background="SteelBlue" Click="btnClick_ListenUDPOn10000"/>
                <Button Content="UDP Debug 2" Margin="3" Width="80" Background="SteelBlue" Click="btnClick_ListenUDPOn20000"/>
            </StackPanel>
    
        </Grid>
    </Window>
        
        
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
    
                optionsToUseForUDPOutput = new SendReceiveOptions<NullSerializer>();
                optionsToUseForUDPInput = new SendReceiveOptions<NullSerializer>();
    
                NetworkComms.EnableLogging();
            }
    
            private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
            {
                NetworkComms.DisableLogging();
                NetworkComms.Shutdown();
            }
    
            #region UDP Output
            SendReceiveOptions optionsToUseForUDPOutput;
            private void btnClick_TxTo10000(object sender, RoutedEventArgs e)
            {
                byte[] byteDataToSend= new byte[] { 1, 2, 3, 4};
    
                using (Packet sendPacket = new Packet("Unmanaged", byteDataToSend, optionsToUseForUDPOutput))
                {
                    UDPConnection.SendObject<byte[]>(sendPacket, new IPEndPoint(IPAddress.Broadcast, 10000), optionsToUseForUDPOutput, ApplicationLayerProtocolStatus.Disabled );
                }
            }
    
            private void btnClick_TxTo20000(object sender, RoutedEventArgs e)
            {
                byte[] byteDataToSend= new byte[] { 11, 12, 13, 14};
    
                using (Packet sendPacket = new Packet("Unmanaged", byteDataToSend, optionsToUseForUDPOutput))
                {
                    UDPConnection.SendObject<byte[]>(sendPacket, new IPEndPoint(IPAddress.Broadcast, 20000), optionsToUseForUDPOutput, ApplicationLayerProtocolStatus.Disabled);
                }
            }
            #endregion
    
            #region UDP Input
            SendReceiveOptions optionsToUseForUDPInput;
            UDPConnectionListener udpListener= null;
            private void btnClick_CreateUDPListener(object sender, RoutedEventArgs e)
            {
                udpListener = new UDPConnectionListener(optionsToUseForUDPInput, ApplicationLayerProtocolStatus.Disabled, UDPOptions.None);
    
                //Add a packet handler for dealing with incoming unmanaged data
                udpListener.AppendIncomingUnmanagedPacketHandler(HandleIncomingUDPPacket);
    
            }
    
            private void btnClick_StopListening(object sender, RoutedEventArgs e)
            {
                if ( udpListener.IsListening )
                    Connection.StopListening(udpListener);
            }
    
            private void btnClick_ListenUDPOn10000(object sender, RoutedEventArgs e)
            {
                Connection.StartListening(udpListener, new IPEndPoint(IPAddress.Any, 10000));
            }
    
            private void btnClick_ListenUDPOn20000(object sender, RoutedEventArgs e)
            {
                Connection.StartListening(udpListener, new IPEndPoint(IPAddress.Any, 20000));
            }
    
            private void HandleIncomingUDPPacket(PacketHeader header, Connection connection, byte[] array)
            {
                string sz = string.Format("Received {0} bytes from ", array.Length);
                System.Diagnostics.Trace.WriteLine(sz + connection.ToString());
            }
    
            #endregion
        }
    

    Cheers

    #2717
    Anonymous
    Inactive

    Heya Don,

    I’ve tried to condense the test case down further to ensure it was easily repeatable.

    I ended up with the following, but this actually appears to work successfully (i.e. no unhandled exceptions):

    public static void RunTest()
    {
        SendReceiveOptions optionsToUseForUDPOutput = new SendReceiveOptions<NullSerializer>();
        SendReceiveOptions optionsToUseForUDPInput = new SendReceiveOptions<NullSerializer>();
    
        UDPConnectionListener udpListener = new UDPConnectionListener(optionsToUseForUDPInput, ApplicationLayerProtocolStatus.Disabled, UDPOptions.None);
    
        //Add a packet handler for dealing with incoming unmanaged data
        udpListener.AppendIncomingUnmanagedPacketHandler(HandleIncomingUDPPacket);
    
        Connection.StartListening(udpListener, new IPEndPoint(IPAddress.Any, 10000));
    
        //Stop listening and attempt to use the same port again
        Connection.StopListening(udpListener);
        Connection.StartListening(udpListener, new IPEndPoint(IPAddress.Any, 10000));
    
        //Stop listening and attempt to use a different port 
        Connection.StopListening(udpListener);
        Connection.StartListening(udpListener, new IPEndPoint(IPAddress.Any, 20000));
    }

    I used version 3.0.1 of the library for the above. Could you possibly run this and see what you get?

    Regards,
    Marc

Viewing 8 posts - 1 through 8 (of 8 total)
  • You must be logged in to reply to this topic.