Skip to content

Instantly share code, notes, and snippets.

@noqisofon
Created December 14, 2010 07:02
Show Gist options
  • Save noqisofon/740092 to your computer and use it in GitHub Desktop.
Save noqisofon/740092 to your computer and use it in GitHub Desktop.
bit.ly/fuB06l のサンプルコードを読みやすくしてみた感じ。
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.IO;
using System.Threading;
namespace demo.multicasting.originator {
// The following ClientOriginator class starts the multicast conversation
// with the ClientTarget class..
// It performs the following main tasks:
// 1)Creates a socket and binds it to the port on which to communicate.
// 2)Specifies that the connection must use an IPv6 address.
// 3)Joins or create a multicast group.
// Note that the multicast address ranges to use are specified
// in the RFC#2375.
// 4)Defines the endpoint to send the data to and starts the
// client target (ClientTarget) thread.
public class ClientOriginator {
/// <summary>
///
/// </summary>
private UdpClient client_originator_;
/// <summary>
///
/// </summary>
private IPAddress group_address_;
/// <summary>
///
/// </summary>
private IPEndPoint client_target_dest_;
/// <summary>
///
/// </summary>
private Thread worker_;
// The ConnectOriginatorAndTarget method connects the
// ClientOriginator with the ClientTarget.
// It performs the following main tasks:
// 1)Creates a UDP client to receive data on a specific port
// using IPv6 addresses.
// 2)Joins or create a multicast group at the specified address.
// 3)Defines the endpoint port to send data to on the ClientTarget.
// 4)Starts the ClientTarget thread that also creates the ClientTarget object.
// Note this method is the counterpart of the
// ClientTarget.StartMulticastConversation().
public bool connectOriginatorAndTarget() {
try {
// Bind and listen on port 2000. This constructor creates a socket
// and binds it to the port on which to receive data. The family
// parameter specifies that this connection uses an IPv6 address.
this.client_originator_ = new UdpClient( 2000, AddressFamily.InterNetworkV6 );
// Join or create a multicast group. The multicast address ranges
// to use are specified in RFC#2375. You are free to use
// different addresses.
// Transform the string address into the internal format.
this.group_address_ = IPAddress.Parse( "FF01::1" );
// Display the multicast address used.
Console.WriteLine( "Multicast Address: [{0}]", this.group_address_ );
// Exercise the use of the IPv6MulticastOption.
Console.WriteLine( "Instantiate IPv6MulticastOption(IPAddress)" );
// Instantiate IPv6MulticastOption using one of the
// overloaded constructors.
IPv6MulticastOption ipv6_multicast_option = new IPv6MulticastOption( this.group_address_ );
// Store the IPAdress multicast options.
IPAddress group = ipv6_multicast_option.Group;
long interface_index = ipv6_multicast_option.InterfaceIndex;
// Display IPv6MulticastOption properties.
Console.WriteLine( "IPv6MulticastOption.Group: [{0}]", group );
Console.WriteLine( "IPv6MulticastOption.InterfaceIndex: [{0}]", interface_index );
// Instantiate IPv6MulticastOption using another
// overloaded constructor.
IPv6MulticastOption ipv6_multicast_option2 = new IPv6MulticastOption( group, interface_index );
// Store the IPAdress multicast options.
group = ipv6_multicast_option2.Group;
interface_index = ipv6_multicast_option2.InterfaceIndex;
// Display the IPv6MulticastOption2 properties.
Console.WriteLine( "IPv6MulticastOption.Group: [{0}]", group );
Console.WriteLine( "IPv6MulticastOption.InterfaceIndex: [{0}]", interface_index );
// Join the specified multicast group using one of the
// JoinMulticastGroup overloaded methods.
this.client_originator_.JoinMulticastGroup( (int)interface_index, group );
// Define the endpoint data port. Note that this port number
// must match the ClientTarget UDP port number which is the
// port on which the ClientTarget is receiving data.
this.client_target_dest_ = new IPEndPoint( this.group_address_, 1000 );
ClientTarget target = new ClientTarget( this.client_target_dest_ );
// Start the ClientTarget thread so it is ready to receive.
this.worker_ = new Thread( new ThreadStart( target.startMulticastConversation ) );
this.worker_.Start();
// Make sure that the thread has started.
Thread.Sleep( 2000 );
return true;
} catch ( Exception e ) {
Console.WriteLine( "[ClientOriginator.ConnectClients] Exception: {0}", e );
return false;
}
}
// The SendAndReceive performs the data exchange
// between the ClientOriginator and the ClientTarget classes.
public string sendAndReceive() {
string ret = string.Empty;
Receiver receiver = new Receiver( this.client_originator_ );
Sender sender = new Sender(this.client_originator_);
// Send data to ClientTarget.
Console.WriteLine( "\nThe ClientOriginator sent:\n" );
sender.originatorSendData( this.client_target_dest_ );
// Receive data from ClientTarget
ret = receiver.receiveUntilStop();
// Stop the ClientTarget thread
worker_.Abort();
// Abandon the multicast group.
client_originator_.DropMulticastGroup( this.group_address_ );
return ret;
}
/// <summary>
/// This is the console application entry point.
/// </summary>
public static void Main() {
ClientOriginator originator = new ClientOriginator();
// Join the multicast group.
if ( originator.connectOriginatorAndTarget() ) {
// Perform a multicast conversation with the ClientTarget.
string ret = originator.sendAndReceive();
Console.WriteLine( "\nThe ClientOriginator received: \n\n{0}", ret );
} else {
Console.WriteLine( "Unable to Join the multicast group" );
}
}
}
}
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.IO;
using System.Threading;
namespace demo.multicasting.originator {
// The ClientTarget class is the receiver of the ClientOriginator
// messages. The StartMulticastConversation method contains the
// logic for exchanging data between the ClientTarget and its
// counterpart ClientOriginator in a multicast operation.
public class ClientTarget {
/// <summary>
///
/// </summary>
private UdpClient client_;
/// <summary>
///
/// </summary>
private IPAddress group_address_;
/// <summary>
///
/// </summary>
public ClientTarget(IPEndPoint endpoint) {
// Bind and listen on port 1000. Specify the IPv6 address family type.
this.client_ = new UdpClient( endpoint.Port, AddressFamily.InterNetworkV6 );
// Join or create a multicast group
this.group_address_ = endpoint.Address;
}
// The following StartMulticastConversation method connects the UDP
// ClientTarget with the ClientOriginator.
// It performs the following main tasks:
// 1)Creates a UDP client to receive data on a specific port and using
// IPv6 addresses. The port is the same one used by the ClientOriginator
// to define its communication endpoint.
// 2)Joins or creates a multicast group at the specified address.
// 3)Defines the endpoint port to send data to the ClientOriginator.
// 4)Receives data from the ClientOriginator until the end of the
// communication.
// 5)Sends data to the ClientOriginator.
// Note this method is the counterpart of the
// ClientOriginator.ConnectOriginatorAndTarget().
public void startMulticastConversation() {
string ret;
// Use the overloaded JoinMulticastGroup method.
// Refer to the ClientOriginator method to see how to use the other
// methods.
this.client_.JoinMulticastGroup( this.group_address_ );
// Define the endpoint data port. Note that this port number
// must match the ClientOriginator UDP port number which is the
// port on which the ClientOriginator is receiving data.
IPEndPoint client_originator_dest = new IPEndPoint( this.group_address_, 2000 );
// Receive data from the ClientOriginator.
Receiver receiver = new Receiver( this.client_ );
ret = receiver.receiveUntilStop();
Console.WriteLine( "\nThe ClientTarget received: \n\n{0}\n", ret );
// Done receiving, now respond to the ClientOriginator.
// Wait to make sure the ClientOriginator is ready to receive.
Thread.Sleep( 2000 );
Console.WriteLine( "\nThe ClientTarget sent:\n" );
Sender sender = new Sender( this.client_ );
sender.targetSendData( client_originator_dest );
// Exit the multicast conversation.
client_.DropMulticastGroup( this.group_address_ );
}
}
}
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.IO;
using System.Threading;
namespace demo.multicasting.originator {
/// <summary>
/// The following Receive class is used by both the ClientOriginator and
/// the ClientTarget class to receive data from one another..
/// </summary>
public class Receiver {
/// <summary>
///
/// </summary>
public Receiver(UdpClient client) {
this.client_ = client;
this.session_teminator_ = "Over";
}
/// <summary>
/// </summary>
/// <remarks>
/// The following static method performs the actual data
/// exchange. In particular, it performs the following tasks:
/// 1)Establishes a communication endpoint.
/// 2)Receive data through this end point on behalf of the
/// caller.
/// 3) Returns the received data in ASCII format.
/// </remarks>
/// <param name="client"></param>
/// <returns></returns>
public string receiveUntilStop() {
StringBuilder text_data_builder = new StringBuilder();
string segment = string.Empty;
ASCIIEncoding ascii = new ASCIIEncoding();
// Establish the communication endpoint.
IPEndPoint endpoint = new IPEndPoint( IPAddress.IPv6Any, 50 );
while ( !segment.Equals( this.session_teminator_ ) ) {
byte[] data = this.client_.Receive( ref endpoint );
segment = ascii.GetString( data );
text_data_builder.AppendLine( segment );
}
return text_data_builder.ToString();
}
/// <summary>
///
/// </summary>
private UdpClient client_;
/// <summary>
///
/// </summary>
private string session_teminator_;
}
}
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.IO;
using System.Threading;
namespace demo.multicasting.originator {
/// <summary>
/// The following Send class is used by both the ClientOriginator and
/// ClientTarget classes to send data to one another.
/// </summary>
public class Sender {
/// <summary>
///
/// </summary>
/// <param name="client"></param>
public Sender(UdpClient client) {
this.client_ = client;
}
/// <summary>
/// The following static method sends data to the ClientTarget on
/// behalf of the ClientOriginator.
/// </summary>
/// <param name="client"></param>
/// <param name="endpoint"></param>
public void originatorSendData(IPEndPoint endpoint) {
Console.WriteLine( new string( GREETINGS ) );
this.client_.Send( getByteArray( GREETINGS ), GREETINGS.Length, endpoint );
Thread.Sleep( 1000 );
Console.WriteLine( new string( NICE ) );
this.client_.Send( getByteArray( NICE ), NICE.Length, endpoint );
Thread.Sleep( 1000 );
Console.WriteLine( new string( EOM ) );
this.client_.Send( getByteArray( EOM ), EOM.Length, endpoint );
}
/// <summary>
/// The following static method sends data to the ClientOriginator on
/// behalf of the ClientTarget.
/// </summary>
/// <param name="client"></param>
/// <param name="endpoint"></param>
public void targetSendData(IPEndPoint endpoint) {
Console.WriteLine( new string( ORIGINATOR_GREETINGS ) );
this.client_.Send( getByteArray( ORIGINATOR_GREETINGS ), ORIGINATOR_GREETINGS.Length, endpoint );
Thread.Sleep( 1000 );
Console.WriteLine( new string( TOO_NICE ) );
this.client_.Send( getByteArray( TOO_NICE ), TOO_NICE.Length, endpoint );
Thread.Sleep( 1000 );
Console.WriteLine( new string( EOM ) );
this.client_.Send( getByteArray( EOM ), EOM.Length, endpoint );
}
//
/// <summary>
/// Internal utility
/// </summary>
/// <param name="cs"></param>
/// <returns></returns>
private static byte[] getByteArray(char[] cs) {
byte[] ret = new byte[cs.Length];
for ( int i = 0; i < cs.Length; i++ )
ret[i] = (byte)cs[i];
return ret;
}
/// <summary>
///
/// </summary>
private UdpClient client_;
/// <summary>
///
/// </summary>
private static char[] GREETINGS = { 'H', 'e', 'l', 'l', 'o', ' ',
'T', 'a', 'r', 'g', 'e', 't', '.' };
/// <summary>
///
/// </summary>
private static char[] NICE = { 'H', 'a', 'v', 'e', ' ', 'a', ' ', 'n', 'i',
'c', 'e', ' ', 'd', 'a', 'y', '.' };
/// <summary>
///
/// </summary>
private static char[] EOM = { 'O', 'v', 'e', 'r' };
/// <summary>
///
/// </summary>
private static char[] ORIGINATOR_GREETINGS = { 'H', 'e', 'l', 'l', 'o', ' ',
'O', 'r', 'i', 'g', 'i', 'n', 'a', 't', 'o', 'r', '!' };
/// <summary>
///
/// </summary>
private static char[] TOO_NICE = { 'Y', 'o', 'u', ' ', 't', 'o', 'o', '.' };
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment