|
VB .NET Multicast Program Example
Create a new console application project and you might use MulticastVB as the name.
|
Next, rename the class to MulticastEndpoint just to reflect the application that we are going to develop.
Add/edit the following Import directives at the top of the file.
Imports System Imports System.Collections Imports System.Net Imports System.Net.Sockets |
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.
In order to test this project, change the Application type: to Console Application and the Startup object: to Sub Main.
Build the project and make sure there is no error.
Run the project. Any error will be thrown by the exception handlers.
|
The following is the sample output.
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.
If the following Windows Security Alert box displayed, click the Unblock button.
Then, we run the 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.