Avatar of Henry Ottiz
Henry Ottiz
 asked on

Message sender via UDP

Hello
maybe i can have some help...

i have a small windows form that i want to use to do 3 things

1) send via UDP 4 lines of message form 4 textboxes (TBline1-4)  to a specific IP address specific in a textbox (TBIP).
2) "broadcast" to all connected devices the message(s) in each of the Textboxes (TBLine1-4)
3) send a PING to ALL devices connected in the same network

finally, those messages need to be changed to ASCII before sending...

here is my code, i can't make it work...
    Dim publisher As New Sockets.UdpClient(0)
    Dim listener As New Sockets.UdpClient(3100)
    Dim RemEP As IPEndPoint ' Dim RemEP As New IPEndPoint(IPAddress.Parse((TBIP.Text)), 3100) 'Dim RemEP As New IPEndPoint(IPAddress.Parse("192.168.199.253"), 3100) 
    Dim RemALL As New IPEndPoint(IPAddress.Any, 3100)

    '** ONE DISPLAY
    Private Sub BtDis_Click(sender As Object, e As EventArgs) Handles BtDis.Click
        Dim sendbytes() As Byte
        Dim TempString As String
        Dim rcvbytes() As Byte
        Dim RemEP As IPEndPoint
        Static pageNumber As Integer = 1

        RemEP = New IPEndPoint(TBIP.Text, 3100)

        Try
            TempString = ""
            TempString &= TBLine1.Text & "^40" & TBLine2.Text & "^80" & TBLine3.Text & "^120" & TBLine4.Text
            TempString &= Chr(2) & TempString & Chr(3)
            If pageNumber < 255 Then pageNumber += 1 Else pageNumber = 1
            sendbytes = ASCII.GetBytes(TempString)

            listener.Send(sendbytes, sendbytes.Length, RemEP)

            Try
                If listener.Available Then
                    rcvbytes = listener.Receive(RemEP)

                End If
            Catch ex As Exception
            End Try
        Catch ex As Exception
        End Try
    End Sub

    '** SEND TO ALL
    Private Sub BtAll_Click(sender As Object, e As EventArgs) Handles BtAll.Click
        Dim sendbytes() As Byte
        Dim TempString As String
        Static pageNumber As Integer = 1
        Dim RemALL As New IPEndPoint(IPAddress.Any, 3100)

        Try
            TempString = ""
            TempString &= TBLine1.Text & "^40" & TBLine2.Text & "^80" & TBLine3.Text & "^120" & TBLine4.Text
            TempString &= Chr(2) & TempString & Chr(3)

            'TempString &= Chr(2) & TBLine1.Text & "^40" & TBLine2.Text & "^80" & TBLine3.Text & "^120" & TBLine4.Text & Chr(3) ' STX & string & ETX //TempString = Chr(2) & TempString & Chr(3) 
            'TempString &= "$"
            'TempString &= TBLine1.Text & "^40" & TBLine2.Text & "^80" & TBLine3.Text & "^120" & TBLine4.Text
            'TempString &= Chr(2) & TempString & Chr(3)
            'TempString &= TBLine1.Text & vbCr & TBLine2.Text & vbCr & TBLine3.Text & vbCr & TBLine4.Text
            'TempString &= TBLine1.Text & "^40" & TBLine2.Text & "^80" & TBLine3.Text & "^120" & TBLine4.Text

            If pageNumber < 255 Then pageNumber += 1 Else pageNumber = 1
            sendbytes = ASCII.GetBytes(TempString)
            listener.Send(sendbytes, sendbytes.Length, RemALL)
        Catch ex As Exception
        End Try

    End Sub

    '**PING
    Private Sub BtPing_Click(sender As Object, e As EventArgs) Handles BtPing.Click
        Dim sendbytes() As Byte
        Dim TempString As String
        Static pageNumber As Integer = 1

        RemEP = New IPEndPoint((TBIP.Text), 3100)

        TBPing.Clear()
        Try
            TempString = ""
            TempString &= "PING"
            TempString &= TempString & vbCr 'TempString &= Chr(2) & TempString & Chr(3)

            If pageNumber < 255 Then pageNumber += 1 Else pageNumber = 1
            sendbytes = ASCII.GetBytes(TempString)
            listener.Send(sendbytes, sendbytes.Length, RemEP)
        Catch ex As Exception
        End Try

    End Sub

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        'Clear()
        listener.Client.ReceiveTimeout = 100
        listener.Client.Blocking = False
    End Sub

    Private Sub Form1_Close(sender As Object, e As EventArgs) Handles MyBase.Closed
        '       listener.Close()
        'listener.Client.Blocking = True
    End Sub


    'TIMER FOR RESPONSE
    Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        Try
            Dim ep As IPEndPoint = New IPEndPoint(IPAddress.Any, 3100)
            Dim rcvbytes() As Byte
            If listener.Available Then
                rcvbytes = listener.Receive(ep)
                TextBox20.Text = ASCII.GetString(rcvbytes)
            End If
        Catch ex As Exception
        End Try
    End Sub

    Private Sub BtnClear_Click(sender As Object, e As EventArgs) Handles BtnClear.Click
        TBIP.Clear()
        TBLine1.Clear()
        TBLine2.Clear()
        TBLine3.Clear()
        TBLine4.Clear()
        TBPing.Clear()
        ' TextBox20.Clear()
    End Sub

    Public Sub Clear()
        TBIP.Clear()
        TBLine1.Clear()
        TBLine2.Clear()
        TBLine3.Clear()
        TBLine4.Clear()
        TBPing.Clear()
        TextBox20.Clear()
    End Sub

Open in new window

Chat / IMNetworking ProtocolsVisual Basic.NET

Avatar of undefined
Last Comment
Bill Bach

8/22/2022 - Mon
Bill Bach

Your code has many different parts to it.  Can you be a BIT more specific than "it doesn't work"?  
- Is it doing ANYTHING?
- Is it returning a compiler error? If so, what error?
- Is it returning a runtime error?  If so, what error?
- How are you sure that it is not working?  UDP is a connectionless protocol, so there is no guarantee of delivery in the first place.  Are you using a tool like Wireshark to see the packet leave the workstation?

Please add a bit more clarity to the question.  Most of us don't mind helping (that's why we are here), but spending time to build a test environment just to try to compile and run your code is a bit out of the norm.

Another good troubleshooting tool is to add some debugging MsgBox calls to the code.  This can tell you exactly where in the code it is any any point, and you can display critical variable values at that point (IP address, message text, etc.).  It will help verify that the data values are what you THINK they are.
Henry Ottiz

ASKER
than kyou for your response, details below

Your code has many different parts to it.  Can you be a BIT more specific than "it doesn't work"?  
- Is it doing ANYTHING?
>> it is supposed to communicate, if you put a fixed IP (parse...) it does, but that is not the intention. on the first part it has to use the specified IP on the TBIP textbox, but when doing so, the ENDPOINT is not working and throwing the following error (code included)

this is the new IPendpoint
  Dim RemEP As New IPEndPoint(IPAddress.Parse(TBIP.Text), 3100)

it does not like it, not sure why, the error is:

An exception of type 'System.NullReferenceException' occurred in SPSS_DIS404.exe but was not handled in user code

it also happens when i try and use the IPaddress.any, when i try to send to all connected devices.

thank you.

PS: the code is separated in 3 sections

- send to 1 device /display
- send to all devices
- send a ping to check how many devices are connected...
Bill Bach

OK.  Let's work it one thing at a time.  First, you corrected the DIM line in this latest post -- but the DIM you are referring to seems to be a global variable!  There is a different DIM for RemEP inside the BtDis_Click function.  I think you need to be changing the local definition instead.  (This is a common issue that arises when you use global variables and locals with the same name.)

Second, the code fragment doesn't indicate the data type of TBIP.Text, but the Parse function needs a String to be sure.  Since you already have tempstring defined, try putting this inside Sub BtDis_Click:
    tempstring = TBIP.Text
    MsgBox "TempString is <" & tempstring & ">"
    RemEP = New IPEndPoint(IPAddress.Parse(TBIP.Text), 3100)

If you have added more MsgBox functions, you might want to post your latest code, too, as that will help determine that all is working as expected...
This is the best money I have ever spent. I cannot not tell you how many times these folks have saved my bacon. I learn so much from the contributors.
rwheeler23
Henry Ottiz

ASKER
hello, Bill,
no additions to the code (message boxes)...

Let me see if I understand, (code below) as yo mention 1 step at a time.

for 1 Ddisplay only, the code should look like this?

    Private Sub BtDis_Click(sender As Object, e As EventArgs) Handles BtDis.Click
        Dim sendbytes() As Byte
        Dim TempString As String
        Dim rcvbytes() As Byte
        Dim RemEP As IPEndPoint
        Static pageNumber As Integer = 1


        'SETUP TO SEND ONLY TO 1 DISPLAY: TBIP.Text
        Try
            TempString = TBIP.Text
            MsgBox("TempString is <" & TempString & ">")
            RemEP = New IPEndPoint(IPAddress.Parse(TBIP.Text), 3100)

            TempString = ""
            TempString &= TBLine1.Text & "^40" & TBLine2.Text & "^80" & TBLine3.Text & "^120" & TBLine4.Text
            TempString &= Chr(2) & TempString & Chr(3)
            If pageNumber < 255 Then pageNumber += 1 Else pageNumber = 1
            sendbytes = ASCII.GetBytes(TempString)

            Try
                If listener.Available Then
                    rcvbytes = listener.Receive(RemEP)
                End If
            Catch ex As Exception
            End Try
        Catch ex As Exception
        End Try
    End Sub
Bill Bach

Sorry for the confusion -- cut&paste error:

        Try
            TempString = TBIP.Text
            MsgBox("TempString is <" & TempString & ">")
            RemEP = New IPEndPoint(IPAddress.Parse(Tempstring), 3100)
Henry Ottiz

ASKER
thanks for your help, but i am not following...

my doubt is that I am not trying to send the TBIP.Text,  I am trying to use that TBIP.Text as my specific IP in :
RemEP = New IPEndPoint(IPAddress.Parse(TBIP.Text), 3100)

my TempString is the combination of the other textboxes (TBLin1-4):
TempString = ""
TempString &= TBLine1.Text & "^40" & TBLine2.Text & "^80" & TBLine3.Text & "^120" & TBLine4.Text
TempString &= Chr(2) & TempString & Chr(3)

that, in theory, (once the connection can be established), will convert to ASCII and send it to the specific device/IP in TBIP.text...
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
ASKER CERTIFIED SOLUTION
Bill Bach

THIS SOLUTION ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
See Pricing Options
Start Free Trial
GET A PERSONALIZED SOLUTION
Ask your own question & get feedback from real experts
Find out why thousands trust the EE community with their toughest problems.
Henry Ottiz

ASKER
thanks!
ok, I see the message box on display that the IP is what I put in the TBIP.Text

Next:
 still no transmission to the specified display...

i entered the text on the TBLInes1-4 but nothing
Bill Bach

Did that fix the Null Pointer Exception, at least?
Bill Bach

Also, in your last code (ID: 41781847) post, this line seems to have been removed:
    listener.Send(sendbytes, sendbytes.Length, RemEP)
I started with Experts Exchange in 2004 and it's been a mainstay of my professional computing life since. It helped me launch a career as a programmer / Oracle data analyst
William Peck
Henry Ottiz

ASKER
it works!!
thanks! for some reason i deleted that line!

ok i will do the rest of programming for the other two buttons and upload the fuinal code,

thanks so much!!!
Henry Ottiz

ASKER
since we are on a roll, two questions that just came to mind

1) to confirm if this code is correct. once i send the PING command, i should receive a response from all devices, how do i separate each response by IP and display it with time and IP
ry
            Dim ep As IPEndPoint = New IPEndPoint(IPAddress.Any, 3100)
            Dim rcvbytes() As Byte
            If listener.Available Then
                rcvbytes = listener.Receive(ep)
                TextBox20.AppendText("Time: " & Now & "/" & Now.Millisecond & "- IP:" & rcvbytes.ToString & vbNewLine)

            End If
        Catch ex As Exception
        End Try

2) how can i display the response sent from the display in ASCII (no conversion) on a separate Textbox?
Bill Bach

1) Yeah -- you got me on THAT one.  ;-)

Remember that UDP transmissions do not allow for guaranteed delivery.  Even if you send a packet, it may not arrive.  Even if it arrives and they send back a reply, it may not make it back. This is especially the case if there are firewalls involved (like with Windows 7).  Also, I wonder what will happen if you suddenly receive back 100 different replies but are unable to process them all quickly enough -- will the OS queue them up for you?  Or will it decide that UDP is non-critical and simply discard the extra packets?

What I believe you should do is to spawn a completely separate thread to handle the listening. If you don't want to do this, then you might be able to enter into a loop for a set period of time (say, 3 seconds).  While you're in this loop, receive any packets that come in and handle them accordingly. At the end of three seconds, assuming no more packets are waiting to be handled, terminate the loop.

I did a quick lookup, and found this page: https://msdn.microsoft.com/en-us/library/system.net.sockets.udpclient.receive(v=vs.110).aspx
Note that the Receive method is a blocking method, and it will halt the thread until a data packet is available.  I assume that "listener.Available" will check to see if a packet is ready to be received?  If so, then you can use this in your loop, too, and make sure to NOT call Receive unless a packet is waiting, to avoid halting your code.

This all reminds me of a project I once implemented on an AT&T StarLAN network in the late 80's to synchronize time between client PCs and a server.  The client sent a NetBIOS broadcast message to request the time and then posted a listener for a reply.  The Server had already posted a listener process, and when it saw a request come in, it broadcast back out the current time, which was then picked up by the client. (If the reply was missed, the odds were that another client would issue another request shortly, and that one would hopefully be seen.)  Of course, back then, it was all done in 8086 assembler code, and the first time I ran it, a bug in the server-side caused the server to reboot itself.  Oops!  Anyway, I digress......

2) Not sure I understand this question, but I'll take a guess: I assume that if you have a textbox already built, you can simply append the contents of the incoming packet to that text box contents and refresh it onscreen.
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
Henry Ottiz

ASKER
thanks I will check this//
 to keep it simple, going back to the responses..
>> how would i display ANY response on 1 of the 2 textboxes, i Undestand on the UDP protocol loosing packages...
>> the other textbox would be the response in ASCII not conveted through the "ASCII command..."
>> if I wanted to change to TCP, would it make it more reliable?

as promised,  here is the code (without the response part that is pending, i will post that section when i get it)

you have been tremendous help!!

  Dim publisher As New Sockets.UdpClient(0)
    Dim listener As New Sockets.UdpClient(3100)


    '** ONE DISPLAY
    Private Sub BtDis_Click(sender As Object, e As EventArgs) Handles BtDis.Click
        Dim sendbytes() As Byte
        Dim TempString As String
        Dim TempIPText As String
        Dim rcvbytes() As Byte
        Dim RemEP As IPEndPoint
        Static pageNumber As Integer = 1


        'SETUP TO SEND ONLY TO 1 DISPLAY: TBIP.Text
        Try
            If TBIP.Text = String.Empty Then
                MsgBox("A DISPLAY IP # MUST BE ENTERED", MsgBoxStyle.Critical)

            Else
                TempIPText = TBIP.Text
                RemEP = New IPEndPoint(IPAddress.Parse(TempIPText), 3100)

                TempString = ""
                TempString &= vbCr & Chr(2) & TBLine1.Text & "^40" & TBLine2.Text & "^80" & TBLine3.Text & "^120" & TBLine4.Text & Chr(3) & vbCr ' TempString &= Chr(2) & TempString & Chr(3)

                If pageNumber < 255 Then pageNumber += 1 Else pageNumber = 1
                sendbytes = ASCII.GetBytes(TempString)
                listener.Send(sendbytes, sendbytes.Length, RemEP)
                Try
                    If listener.Available Then
                        rcvbytes = listener.Receive(RemEP)
                    End If
                Catch ex As Exception
                End Try
            End If
        Catch ex As Exception
        End Try
    End Sub

    '** 'SEND TO ALL DISPLAYS - BROADCAST
    Private Sub BtAll_Click(sender As Object, e As EventArgs) Handles BtAll.Click
        Dim sendbytes() As Byte
        Dim TempString As String
        Dim rcvbytes() As Byte
        Dim RemEP As IPEndPoint
        Static pageNumber As Integer = 1

        Try
            RemEP = New IPEndPoint(IPAddress.Broadcast, 3100)

            TempString = ""
            TempString &= vbCr & Chr(2) & TBLine1.Text & "^40" & TBLine2.Text & "^80" & TBLine3.Text & "^120" & TBLine4.Text & Chr(3) & vbCr ' TempString &= Chr(2) & TempString & Chr(3)

            If pageNumber < 255 Then pageNumber += 1 Else pageNumber = 1
            sendbytes = ASCII.GetBytes(TempString)
            listener.Send(sendbytes, sendbytes.Length, RemEP)
            Try
                If listener.Available Then
                    rcvbytes = listener.Receive(RemEP)
                End If
            Catch ex As Exception
            End Try
        Catch ex As Exception
        End Try
    End Sub

    '**'SEND PING TO ALL 
    Private Sub BtPing_Click(sender As Object, e As EventArgs) Handles BtPing.Click
        Dim sendbytes() As Byte
        Dim TempString As String
        Dim rcvbytes() As Byte
        Dim RemEP As IPEndPoint
        Static pageNumber As Integer = 1

        Try
            RemEP = New IPEndPoint(IPAddress.Broadcast, 3100)

            TempString = ""
            TempString &= vbCr & Chr(2) & "PING" & Chr(3) & vbCr

            If pageNumber < 255 Then pageNumber += 1 Else pageNumber = 1
                sendbytes = ASCII.GetBytes(TempString)
                listener.Send(sendbytes, sendbytes.Length, RemEP)
                Try
                    If listener.Available Then
                        rcvbytes = listener.Receive(RemEP)
                    End If
                Catch ex As Exception
                End Try

        Catch ex As Exception
        End Try

    End Sub

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        'Clear()
        listener.Client.ReceiveTimeout = 100
        listener.Client.Blocking = False
    End Sub
End Class 

Open in new window

Henry Ottiz

ASKER
how about this?
i was thinking on putting in a timer routine...
 Dim ep As New IPEndPoint(IPAddress.Any, 0)
        Dim receivingUdpClient As New UdpClient(3100)

        Try
            Dim rcvbytes() As Byte = receivingUdpClient.Receive(ep)
            If listener.Available Then
               
                Dim response As String = Encoding.ASCII.GetString(rcvbytes)
                TextBox20.AppendText("Time: " & Now & "/" & "- IP:" & ep.Address.ToString() & "message" & rcvbytes.ToString & vbNewLine)
              
            End If
        Catch ex As Exception
        End Try

Open in new window

Bill Bach

That looks like it would work.  TCP would certainly be more reliable, but you have to set up and tear down the connections, so it is more work and slower, too.  Ultimately, it is just a question of whether you MUST have the replies, or if this is just a "nice thing".
Experts Exchange has (a) saved my job multiple times, (b) saved me hours, days, and even weeks of work, and often (c) makes me look like a superhero! This place is MAGIC!
Walt Forbes
Henry Ottiz

ASKER
thanks bill!
i will test it and if it works will upload the final code all together...
Bill Bach

This answer resolved the initial problems with the code.