The trouble with the UDPClient class in .NET

Started by VelMurugan, Dec 13, 2008, 11:20 PM

Previous topic - Next topic

VelMurugan

The trouble with the UDPClient class in .NET

Microsoft, in its infinite wisdom, built this class in .NET as a simplified method for UDP communication. The one critical thing they forgot to include was a simple time-out feature.

What's wrong with not having a time-out? Plenty, if you have one end of the transmission expecting to receive data, and the source of the transmission decided to go belly-up. If you use the UDPClient.Receive method, and the application sending the message does not send the message, then that UDPClient.Receive method will block forever--at least until the application is closed by the user.

A rather nasty way of handling such a situation. By the very nature of UDP, packets can get lost and never be received, causing the application to wait forever, or a bug in the sending application may simply cause it to never send the message that is expected.

Why on earth Microsoft did not put a time-out feature in this class is beyond me. What this means is that if you are doing any real programming you'll find the UDPClient class to be hopelessly inadequate. You'll have to instead use the more generic Socket Class to accomplish your task.

Below is a code sample that uses the Socket Class to accomplish the tasks that the UDPClient is meant to do, but with a timeout.

The UDPClient Class is for synchronized data transmission. If you are trying to do asynchronized transmission, you would have had to use the Socket class, anyhow.

Imports System.Net.Sockets

    Protected Shared Function UDPDataTransmit( _
            ByVal sBuff() As Byte, ByRef rBuff() As Byte, _
            ByVal IP As String, ByVal Port As Integer) As Integer 'Returns # bytes received
        Dim retstat As Integer
        Dim Sck As Sockets.Socket
        Dim Due As DateTime
        Dim Encrp As IPEndPoint
        Try
            Sck = New Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp)
            Sck.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 10000)
            Sck.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, 10000)

            Encrp = New IPEndPoint(IPAddress.Parse(IP), Port)
            retstat = Sck.SendTo(sBuff, 0, sBuff.Length, SocketFlags.None, Encrp)
            If retstat > 0 Then
                Due = Now.AddMilliseconds(10000) '10 second time-out
                Do While Sck.Available = 0 AndAlso Now < Due
                Loop
                If Sck.Available = 0 Then
                    'timed-out
                    retstat = -3
                    Return retstat
                End If
                ReDim rBuff(Sck.Available - 1)
                retstat = Sck.ReceiveFrom(rBuff, 0, Sck.Available, SocketFlags.None, CType(Encrp, EndPoint))
            Else
                retstat = -1 ' fail on send
            End If
        Catch ex As Exception
            'General Exception received--add code here to analyze the exception. A messagebox would be one idea.
            retstat = -2
        Finally
            Sck.Close() 'Always close the socket when done.
        End Try
        Return retstat
    End Function


Source : VBCity