< C# Multicast Program Example | Main | Raw Socket & IPv4, ICMP, TCP Listeners >


 

Chapter 8 Part 26:

Client (and Server) Sockets Communication

 

 

What do we have in this chapter 8 Part 26?

  1. VB .NET Multicast Program Example

 

VB .NET Multicast Program Example

 

Create a new console application project and you might use MulticastVB as the name.

 

VB .NET Multicast Program Example - creating a new class library project in the VS 2008

 

 

Next, rename the class to MulticastEndpoint just to reflect the application that we are going to develop.

 

VB .NET Multicast Program Example - renaming the class name

 

 

VB .NET Multicast Program Example - entering the new name for the class

 

Add/edit the following Import directives at the top of the file.

 

Imports System

Imports System.Collections

Imports System.Net

Imports System.Net.Sockets

 

VB .NET Multicast Program Example - adding the Imports directives

 

Add the following code for the MulticastEndpoint class.

 

 

 

 

' This class represents a multicast socket. It keeps track of what address

' the socket is bound to, what group is joined, etc.

Public Class MulticastEndpoint

    Public localInterfaceList, multicastJoinList As ArrayList

    Public mcastSocket As Socket

    Public bindAddress As IPAddress

    Public bufferSize As Integer

    Public localport As Integer

    Public dataBuffer() As Byte

    Private Shared mcastOption1 As MulticastOption

 

    ' Simple constructor for the        

    Public Sub New()

        localInterfaceList = New ArrayList

        multicastJoinList = New ArrayList

        bufferSize = 512

    End Sub

 

    Private Shared Sub MulticastOptionProperties()

        Console.WriteLine(("Current multicast group is: " + mcastOption1.Group.ToString()))

        Console.WriteLine(("Current multicast local address is: " + mcastOption1.LocalAddress.ToString()))

    End Sub 'MulticastOptionProperties

 

    ' This method creates the socket, joins it to the given multicast groups, and initializes

    ' the send/receive buffer. Note that the local bind address should be the wildcard address

    ' because it is possible to join multicast groups on one or more local interface and if

    ' a socket is bound to an explicit local interface, it can lead to user confusion (although

    ' this does currently work on Windows OSes).

    '

    ' <param name="port">Local port to bind socket to</param>

    Public Sub Create(ByVal port As Integer, ByVal bufferLength As Integer)

 

        localport = port

 

        Try

            Console.WriteLine("Creating the socket, joins it to the given multicast groups,")

            Console.WriteLine(" and initializes the send/receive buffer...")

            ' If no bind address was specified, pick an appropriate one based on the multicast

            ' group being joined.

            If IsNothing(bindAddress) Then

                Dim tmpAddr As IPAddress = multicastJoinList(0)

 

                If (tmpAddr.AddressFamily = AddressFamily.InterNetwork) Then

                    bindAddress = IPAddress.Any

                ElseIf (tmpAddr.AddressFamily = AddressFamily.InterNetworkV6) Then

                    bindAddress = IPAddress.IPv6Any

                End If

            End If

 

            ' Create the UDP socket

            mcastSocket = New Socket( _

                bindAddress.AddressFamily, _

                SocketType.Dgram, _

                0 _

                )

            Console.WriteLine("Socket() is OK...")

            Console.WriteLine("{0} multicast socket created", bindAddress.AddressFamily.ToString())

 

            ' Bind the socket to the local endpoint

            Dim bindEndPoint As IPEndPoint = New IPEndPoint(bindAddress, port)

 

            mcastSocket.Bind(bindEndPoint)

            Console.WriteLine("Bind() is OK...")

            Console.WriteLine("Multicast socket bound to: {0}", bindEndPoint.ToString())

 

            ' Join the multicast group

            Console.WriteLine("Joining the multicast group...")

            Dim i, j As Integer

            For i = 0 To multicastJoinList.Count - 1

                For j = 0 To localInterfaceList.Count - 1

                    ' Create the MulticastOption structure which is required to join the multicast group

                    If (mcastSocket.AddressFamily = AddressFamily.InterNetwork) Then

                        Dim mcastOption As MulticastOption = New MulticastOption(CType(multicastJoinList(i), IPAddress), CType(localInterfaceList(j), IPAddress))

 

                        mcastSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, mcastOption)

 

                    ElseIf (mcastSocket.AddressFamily = AddressFamily.InterNetworkV6) Then

                        Dim ipv6McastOption As IPv6MulticastOption = New IPv6MulticastOption( _

                            multicastJoinList(i), _

                            localInterfaceList(j).ScopeId _

                            )

                        mcastSocket.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.AddMembership, ipv6McastOption)

                    End If

                    Console.WriteLine("Joined multicast group {0} on interface {1}", multicastJoinList(i).ToString(), localInterfaceList(j).ToString())

                Next

            Next

 

            ' Allocate the send and receive buffer

            Console.WriteLine("Allocating the send and receive buffer...")

            ReDim dataBuffer(bufferLength)

 

        Catch err As SocketException

            Console.WriteLine("Exception occurred when creating multicast socket: {0}", err.Message)

            Throw

        End Try

    End Sub

 

    ' This method drops membership to any joined groups. To do so, you have to

    ' drop the group exactly as you joined it -- that is the local interface

    ' and multicast group must be the same as when it was joined. Also note

    ' that it is not required to drop joined groups before closing a socket.

    ' When a socket is closed all multicast joins are dropped for you -- this

    ' routine just illustrates how to drop a group if you need to in the middle

    ' of the lifetime of a socket.

    Public Sub LeaveGroups()

        Try

            Dim i, j As Integer

 

            Console.WriteLine("Dropping membership to any joined groups...")

            For i = 0 To multicastJoinList.Count - 1

                For j = 0 To localInterfaceList.Count - 1

 

                    ' Create the MulticastOption structure which is required to drop the

                    '    multicast group (the same structure used to join the group is

                    '    required to drop it).

                    If (mcastSocket.AddressFamily = AddressFamily.InterNetwork) Then

                        ' Object to IPAddress - narrow conversion

                        Dim mcastOption As MulticastOption = New MulticastOption(CType(multicastJoinList(i), IPAddress), CType(localInterfaceList(j), IPAddress))

 

                        mcastSocket.SetSocketOption( _

                            SocketOptionLevel.IP, _

                            SocketOptionName.DropMembership, _

                            mcastOption _

                            )

                    ElseIf (mcastSocket.AddressFamily = AddressFamily.InterNetworkV6) Then

                        Dim ipv6McastOption As IPv6MulticastOption = New IPv6MulticastOption( _

                            multicastJoinList(i), _

                            localInterfaceList(j).ScopeId _

                            )

 

                        mcastSocket.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.DropMembership, ipv6McastOption)

                    End If

                    Console.WriteLine("Dropping multicast group {0} on interface {1}", _

                        multicastJoinList(i).ToString(), _

                        localInterfaceList(j).ToString() _

                        )

                Next

            Next

        Catch

            Console.WriteLine("LeaveGroups: No multicast groups joined")

        End Try

    End Sub

 

    ' This method sets the outgoing interface when a socket sends data to a multicast

    ' group. Because multicast addresses are not routable, the network stack simply

    ' picks the first interface in the routing table with a multicast route. In order

    ' to change this behavior, the MulticastInterface option can be used to set the

    ' local interface on which all outgoing multicast traffic is to be sent (for this

    ' socket only). This is done by converting the 4 byte IPv4 address (or 16 byte

    ' IPv6 address) into a byte array.

    '

    ' <param name="sendInterface"></param>

    Public Sub SetSendInterface(ByVal sendInterface As IPAddress)

        ' Set the outgoing multicast interface

        Console.WriteLine("setting the outgoing interface when a socket sends data to a multicast group...")

        Try

            If (mcastSocket.AddressFamily = AddressFamily.InterNetwork) Then

                mcastSocket.SetSocketOption( _

                    SocketOptionLevel.IP, _

                    SocketOptionName.MulticastInterface, _

                    sendInterface.GetAddressBytes() _

                    )

 

            Else

                Dim interfaceArray() As Byte = BitConverter.GetBytes(CInt(sendInterface.ScopeId))

 

                mcastSocket.SetSocketOption( _

                    SocketOptionLevel.IPv6, _

                    SocketOptionName.MulticastInterface, _

                    interfaceArray _

                    )

            End If

            Console.WriteLine("Setting multicast send interface to: " + sendInterface.ToString())

        Catch err As SocketException

            Console.WriteLine("SetSendInterface: Unable to set the multicast interface: {0}", _

                err.Message)

            Throw

        End Try

    End Sub

 

    ' This method takes a string and repeatedly copies it into the send buffer

    ' to the length of the send buffer.

    ' </summary>

    ' <param name="message">String to copy into send buffer</param>

    Public Sub FormatBuffer(ByVal message As String)

        Dim byteMessage() As Byte = System.Text.Encoding.ASCII.GetBytes(message)

        Dim index As Integer = 0

 

        Console.WriteLine("Formatting string in send buffer...")

        ' First convert the string to bytes and then copy into send buffer

        Do While index < dataBuffer.Length

            Dim j As Integer

 

            For j = 0 To byteMessage.Length - 1

 

                dataBuffer(index) = byteMessage(j)

                index = index + 1

 

                ' Make sure we don't go past the send buffer length

                If (index >= dataBuffer.Length) Then

                    Exit For

                End If

            Next

        Loop

    End Sub

End Class

 

 

Next, add another class and code, you might name it MulticastSample.

 

'This is the main class which makes up the multicast sample.

Class MulticastSample

 

    ' This method prints usage information for multicast sample

    Shared Sub usage()

        Console.WriteLine("Executable_file_name [/i ip] [/b ip] [/m ip] [/p port] [/x num] [/t text]")

        Console.WriteLine("Available options:")

        Console.WriteLine("              [/n count] [/s | /r]")

        Console.WriteLine("   /i ip                    Local interface to join multicast group(s) on")

        Console.WriteLine("   /b ip                   Local IP to bind the socket to")

        Console.WriteLine("   /m ip                  Multicast group to join")

        Console.WriteLine("   /p port   Port to listen on or send to")

        Console.WriteLine("   /x size   Length of send or receive buffer")

        Console.WriteLine("   /t text     Text message to put in send buffer")

        Console.WriteLine("   /n count  Number of times to send or receive")

        Console.WriteLine("   /s        Send data to a multicast group")

        Console.WriteLine("   /r                        Receive data send to the group")

        Console.WriteLine()

    End Sub

 

    ' This is the main routine which parses the command line and creates the

    ' multicast socket as given by the command line parameters. The sample

    ' can either be invoked as a multicast sender or receiver.

    '

    ' To invoke as a multicast receiver:

    '     Executable_file_name /r /i 10.10.10.1 /m 234.6.6.6

    ' To invoke as a multicast sender:

    '     Executable_file_name /s /i 10.10.10.99 /m 234.6.6.6

    '

    ' <param name="appArguments">Command line arguments</param>

    Shared Sub Main()

        Dim mcastEndpoint As MulticastEndpoint = New MulticastEndpoint

        Dim textMessage As String = "Hello World"

        Dim port As Integer = 0

        Dim bufferLength As Integer = 1024

        Dim opCount As Integer = 10

        Dim isSender As Boolean = True

 

        ' Parse the command line

        Dim appArguments As String() = Environment.GetCommandLineArgs()

        Dim i As Integer

 

        For i = 1 To appArguments.GetUpperBound(0) - 1

 

            Try

                Dim CurArg() As Char = appArguments(i).ToCharArray(0, appArguments(i).Length)

 

                If (CurArg(0) = "-") Or (CurArg(0) = "/") Then

 

                    Select Case Char.ToLower(CurArg(1), System.Globalization.CultureInfo.CurrentCulture)

                        Case "b"

                            ' Address to bind multicast socket to

                            i = i + 1

                            mcastEndpoint.bindAddress = IPAddress.Parse(appArguments(i))

                        Case "c"

                            ' How many times to send or receive

                            i = i + 1

                            opCount = System.Convert.ToInt32(appArguments(i).ToString())

                        Case "i"

                            ' Local interface to join group(s) on

                            i = i + 1

                            mcastEndpoint.localInterfaceList.Add(IPAddress.Parse(appArguments(i)))

                        Case "m"

                            ' Multicast group to join

                            i = i + 1

                            mcastEndpoint.multicastJoinList.Add(IPAddress.Parse(appArguments(i)))

                        Case "p"

                            ' Port number to bind to or send to

                            i = i + 1

                            port = System.Convert.ToInt32(appArguments(i).ToString())

                        Case "r"

                            ' Application invoked as receiver

                            isSender = False

                        Case "s"

                            ' Application invoked as sender

                            isSender = True

                        Case "t"

                            ' Text message to send

                            i = i + 1

                            textMessage = appArguments(i)

                        Case "x"

                            ' Length of send/receive buffer

                            i = i + 1

                            bufferLength = System.Convert.ToInt32(appArguments(i).ToString())

                        Case Else

                            usage()

                            Exit Sub

                    End Select

                End If

 

            Catch e As System.IndexOutOfRangeException

                usage()

                Exit Sub

            End Try

        Next

 

        ' Make sure user specified at least on multicast group and interface to join

        If ((mcastEndpoint.multicastJoinList.Count = 0) Or (mcastEndpoint.localInterfaceList.Count = 0)) Then

            Console.WriteLine("Please specify a multicast group and interface to join on!")

            usage()

            Exit Sub

        End If

 

        Try

            ' Now, create the multicast socket

            Console.WriteLine("Creating the multicast socket...")

            If (isSender = True) Then

                ' For the sender, we don't care what the local port the socket is bound to

                'If the sender we don't care what local port we bind to

                mcastEndpoint.Create(0, bufferLength)

            Else

                mcastEndpoint.Create(port, bufferLength)

            End If

            If isSender = True Then

                Dim destinationGroup As IPEndPoint = New IPEndPoint _

                    (CType(mcastEndpoint.multicastJoinList(0), IPAddress), port)

 

                Dim rc As Integer

 

                ' Set the send interface for all outgoing multicast packets

                Console.WriteLine("Setting the send interface for all outgoing multicast packets...")

                mcastEndpoint.SetSendInterface(mcastEndpoint.localInterfaceList(0))

                mcastEndpoint.FormatBuffer(textMessage)

 

                ' Send the message the requested number of times

                Console.WriteLine("Sending the message the requested number of times...")

                For i = 0 To opCount - 1

                    Try

                        rc = mcastEndpoint.mcastSocket.SendTo(mcastEndpoint.dataBuffer, destinationGroup)

                        Console.WriteLine("Sent {0} bytes to {1}", rc, destinationGroup.ToString())

                    Catch err As SocketException

                        Console.WriteLine("Multicast SendTo() failed: " + err.Message)

                    End Try

                Next

            Else

                Dim senderEndPoint As IPEndPoint = New IPEndPoint(CType(mcastEndpoint.localInterfaceList(0), IPAddress), 0)

                Dim castSenderEndPoint As EndPoint = CType(senderEndPoint, EndPoint)

                Dim rc As Integer

 

                For i = 0 To opCount - 1

                    Try

                        rc = mcastEndpoint.mcastSocket.ReceiveFrom(mcastEndpoint.dataBuffer, castSenderEndPoint)

                        senderEndPoint = CType(castSenderEndPoint, IPEndPoint)

                        Console.WriteLine("Received {0} bytes from {1}: '{2}'", _

                            rc, _

                            senderEndPoint.ToString(), _

                            System.Text.Encoding.ASCII.GetString(mcastEndpoint.dataBuffer, 0, rc) _

                            )

                    Catch err As SocketException

                        Console.WriteLine("Multicast ReceiveFrom() failed: " + err.Message)

                    End Try

                Next

            End If

            ' Drop membership to groups. This isn't required in this sample as closing the socket

            '    will implicitly leave all groups joined, but it's a good practice.

            mcastEndpoint.LeaveGroups()

        Catch

            Console.WriteLine("An error occurred creating the multicast socket")

        Finally

            If (Not IsNothing(mcastEndpoint.mcastSocket)) Then

                Console.WriteLine("Closing multicast socket...")

                mcastEndpoint.mcastSocket.Close()

                mcastEndpoint = Nothing

            End If

        End Try

    End Sub

End Class

 

Let change the DLL to EXE type program so that we can run it n console mode. Select the project folder > Right click mouse > Select Properties context menu.

 

VB .NET Multicast Program Example - invoking the project's property page in VS 2008 IDE

 

In order to test this project, change the Application type: to Console Application and the Startup object: to Sub Main.

 

VB .NET Multicast Program Example - changing the application type from DLL to EXE and setting the startup to Main() subroutine in order to test this project

 

Build the project and make sure there is no error.

 

VB .NET Multicast Program Example - build the project

 

Run the project. Any error will be thrown by the exception handlers.

 

VB .NET Multicast Program Example run the project from the VS 2008 IDE

 

The following is the sample output.

 

VB .NET Multicast Program Example - a sample output without arguments supplied

 

The following are sample outputs when run at the command prompt for sender and receiver. This program example was tested on a simple private network with two computers connected using the peer-to-peer cable (cross cable). You may want to test on the real network. Firstly, we run the receiver.

 

VB .NET Multicast Program Example - a sample output that acts as receiver

 

If the following Windows Security Alert box displayed, click the Unblock button.

 

VB .NET Multicast Program Example - unblocking the Windows firewall

 

Then, we run the sender.

 

VB .NET Multicast Program Example - a sample output that acts as a sender

 

The following is the receiver output screenshot when the communication was completed. You may want to test this program on real network with more senders.

 

VB .NET Multicast Program Example - the receiver screen when the communication was completed

 


< C# Multicast Program Example | Main | Raw Socket & IPv4, ICMP, TCP Listeners >