Netduino home hardware projects downloads community

Jump to content


The Netduino forums have been replaced by new forums at community.wildernesslabs.co. This site has been preserved for archival purposes only and the ability to make new accounts or posts has been turned off.
Photo

Micro.Udp.Cast


  • Please log in to reply
3 replies to this topic

#1 Robert Hugo

Robert Hugo

    Advanced Member

  • Members
  • PipPipPip
  • 35 posts

Posted 25 May 2015 - 02:29 AM

Here is a Micro.NET class file (Micro.Udp.Cast.cs) that uses Multicast functionality. I seem to be having problems with the receiving buffer. (From tablet TO N3:) If I send 5 characters initially, I get 0 received, if I then send 15, I get 5, and if I then send 25, I get 15, and so on. It's like the buffer size is (re)set from the previous received size.

 

Anyways, this works on the N3 and N2+.

namespace Micro.Udp
{
	public class Cast
	{
		#region "Event Handling"
		public class DataReceivedEventArgs
		{
			public byte[] Bytes { get; private set; }
			public System.Net.EndPoint Remote { get; private set; }

			public DataReceivedEventArgs(byte[] bytes, System.Net.EndPoint remote)
			{
				Bytes = bytes;
				Remote = remote;
			}
		}

		private DataReceivedEventHandler DataReceivedExternal;

		private System.Threading.Thread DataReceivedThread;

		public delegate void DataReceivedEventHandler(object sender, DataReceivedEventArgs e);

		protected virtual void RaiseDataReceivedEvent(DataReceivedEventArgs e)
		{
			DataReceivedEventHandler eventHandler = DataReceivedExternal;

			if (eventHandler != null)
				eventHandler(this, e);
		}
		#endregion

		public System.Net.IPEndPoint Remote { get; private set; }

		public System.Net.Sockets.Socket Socket { get; private set; }

		public Cast(System.Net.IPEndPoint remote, DataReceivedEventHandler dataReceivedEventHandler)
		{
			Remote = remote;

			Socket = new System.Net.Sockets.Socket(System.Net.Sockets.AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Dgram, System.Net.Sockets.ProtocolType.Udp);
			Socket.SetSocketOption(System.Net.Sockets.SocketOptionLevel.IP, System.Net.Sockets.SocketOptionName.DontFragment, true);
			//Socket.SetSocketOption(System.Net.Sockets.SocketOptionLevel.IP, System.Net.Sockets.SocketOptionName.IpTimeToLive, 127);
			//Socket.SetSocketOption(System.Net.Sockets.SocketOptionLevel.Socket, System.Net.Sockets.SocketOptionName.ReuseAddress, true);
			//Socket.SetSocketOption(System.Net.Sockets.SocketOptionLevel.Socket, System.Net.Sockets.SocketOptionName.ReceiveBuffer, 1024);
			//Socket.SetSocketOption(System.Net.Sockets.SocketOptionLevel.Socket, System.Net.Sockets.SocketOptionName.SendBuffer, 1024);
			Socket.Bind(new System.Net.IPEndPoint(System.Net.IPAddress.Any, Remote.Port));
			if (new System.Text.RegularExpressions.Regex(@"2(?:2[4-9]|3\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d?|0)){3}").IsMatch(Remote.Address.ToString()))
			{
				//byte[] multicastOpt = new byte[] { 224, 5, 6, 7, 0, 0, 0, 0 };
				byte[] multicastOpt = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 };
				System.Array.Copy(Remote.Address.GetAddressBytes(), multicastOpt, 0);
				System.Array.Copy(Remote.Address.GetAddressBytes(), multicastOpt, 4);
				Socket.SetSocketOption(System.Net.Sockets.SocketOptionLevel.IP, System.Net.Sockets.SocketOptionName.MulticastTimeToLive, 127);
				Socket.SetSocketOption(System.Net.Sockets.SocketOptionLevel.IP, System.Net.Sockets.SocketOptionName.AddMembership, multicastOpt);
			}

			DataReceivedExternal = dataReceivedEventHandler;

			DataReceivedThread = new System.Threading.Thread(DataReceivedInternal);
			DataReceivedThread.Start();
		}

		private void DataReceivedInternal()
		{
			System.Net.EndPoint remoteEP = (System.Net.EndPoint)new System.Net.IPEndPoint(System.Net.IPAddress.Parse("0.0.0.0"), Remote.Port);

			while (true)
			{
				if (Socket.Available > 0)
				{
					byte[] buffer = new byte[Socket.Available];

					Socket.ReceiveFrom(buffer, ref remoteEP);

					RaiseDataReceivedEvent(new DataReceivedEventArgs(buffer, remoteEP));
				}
			}
		}

		public void SendBytes(byte[] bytes)
		{
			Socket.SendTo(bytes, Remote);
		}
		public void SendString(string text)
		{
			SendBytes(System.Text.Encoding.UTF8.GetBytes("Netduino: " + text));
		}
	}
}


#2 Robert Hugo

Robert Hugo

    Advanced Member

  • Members
  • PipPipPip
  • 35 posts

Posted 25 May 2015 - 02:37 AM

This is the Windows (8.1) Store apps equivalent class file (Universal.Udp.cs): 

using System;

namespace Universal.Udp
{
	public class EndPoint
	{
		public Windows.Networking.HostName HostName { get; private set; }
		public string ServiceName { get; private set; }

		public EndPoint(Windows.Networking.HostName hostName, string serviceName)
		{
			HostName = hostName;
			ServiceName = serviceName;
		}

		public override string ToString()
		{
			return HostName.ToString() + ':' + ServiceName;
		}
	}

	public class Cast
		: Flux.ManagedDisposable
	{
		#region "Event Handling"
		public class DataReceivedEventArgs : System.EventArgs
		{
			public byte[] Bytes { get; private set; }
			public EndPoint Remote { get; private set; }

			public DataReceivedEventArgs(byte[] bytes, EndPoint remote)
			{
				Bytes = bytes;
				Remote = remote;
			}
		}

		public event System.EventHandler<DataReceivedEventArgs> DataReceived;

		protected virtual void RaiseDataReceivedEvent(DataReceivedEventArgs e)
		{
			System.EventHandler<DataReceivedEventArgs> handler = DataReceived;

			if (handler != null)
				handler(this, e);
		}
		#endregion

		public EndPoint Remote { get; private set; }
		public Windows.Networking.Sockets.DatagramSocket Socket { get; private set; }

		public Cast(EndPoint remote)
		{
			Remote = remote;

			Socket = new Windows.Networking.Sockets.DatagramSocket();
			Socket.Control.DontFragment = true;
			Socket.Control.InboundBufferSizeInBytes = 1024;
			Socket.MessageReceived += Socket_MessageReceived;
			Socket.BindServiceNameAsync(Remote.ServiceName.ToString()).GetResults();
			if (System.Text.RegularExpressions.Regex.IsMatch(Remote.HostName.ToString(), @"2(?:2[4-9]|3\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d?|0)){3}"))
				Socket.JoinMulticastGroup(Remote.HostName);
		}
		~Cast()
		{
			Dispose();
		}

		private void Socket_MessageReceived(Windows.Networking.Sockets.DatagramSocket sender, Windows.Networking.Sockets.DatagramSocketMessageReceivedEventArgs args)
		{
			using (Windows.Storage.Streams.DataReader dataReader = args.GetDataReader())
			{
				byte[] bytes = new byte[dataReader.UnconsumedBufferLength];

				dataReader.ReadBytes(bytes);

				RaiseDataReceivedEvent(new DataReceivedEventArgs(bytes, new EndPoint(args.RemoteAddress, args.RemotePort)));
			}
		}

		async public void SendDataAsync(byte[] bytes)
		{
			using (Windows.Storage.Streams.IOutputStream outputStream = await Socket.GetOutputStreamAsync(Remote.HostName, Remote.ServiceName.ToString()))
			{
				using (Windows.Storage.Streams.DataWriter dataWriter = new Windows.Storage.Streams.DataWriter(outputStream))
				{
					dataWriter.WriteBytes(bytes);

					await dataWriter.StoreAsync();
				}
			}
		}

		protected override void DisposeManagedResources()
		{
			if (Socket != null)
			{
				Socket.Dispose();
				Socket = null;
			}
		}
	}
}

The Flux.Disposable.cs file below is also needed:

namespace Flux
{
	/// <summary>Base Implementation of System.IDisposable. Only needed if lots of managed resources needs cleaning up right away (as opposed to wait for the GC).</summary>
	public class ManagedDisposable
		: System.IDisposable
	{
		protected bool IsDisposed { get; set; } // Disposed has already occured?

		public virtual void Dispose()
		{
			if (!IsDisposed)
			{
				DisposeManagedResources();

				IsDisposed = true;
			}
		}

		/// <summary>Override for disposal of managed resources.</summary>
		protected virtual void DisposeManagedResources() { }
	}

	/// <summary>Extended implementation of (System.IDisposable) ManagedDisposable. Only needed if directly using unmanaged resources (add the call "Dispose(false)" inside the finalizer) , and possibly if lots of managed resources needs cleaning up right away.</summary>
	public class UnmanagedDisposable :
		ManagedDisposable
	{
		public override void Dispose()
		{
			Dispose(true);

			System.GC.SuppressFinalize(this); // Inform GC that our resources has already been cleaned up, no need to call finalize later.
		}

		/// <summary>Overload implementation of dispose; if isDisposing = false the method has been called by the runtime from inside the finalizer and only unmanaged resources should be disposed, else if isDisposing = true the method has been called directly or indirectly by a user's code and both managed and unmanaged resources should be disposed.</summary>
		public void Dispose(bool isDisposing)
		{
			if (!IsDisposed)
			{
				if (isDisposing)
					base.Dispose();

				DisposeUnmanagedResources();

				if (!isDisposing)
					IsDisposed = true;
			}
		}

		/// <summary>Override for disposal of unmanaged resources.</summary>
		protected virtual void DisposeUnmanagedResources() { }
	}
}



#3 Robert Hugo

Robert Hugo

    Advanced Member

  • Members
  • PipPipPip
  • 35 posts

Posted 25 May 2015 - 02:43 AM

Here is a N3 sample snippet:

namespace NetduinoApplication1
{
	public class Program
	{
		static Micro.Udp.Cast _udpCast = null;

		public static void Main()
		{
			while (IPAddress.GetDefaultLocalAddress() == IPAddress.Any) ;

			_udpCast = new Micro.Udp.Cast(new System.Net.IPEndPoint(System.Net.IPAddress.Parse("224.5.6.7"), 4567), UdpCast_DataReceived);	
		}

		static void UdpCast_DataReceived(object sender, Micro.Udp.Cast.DataReceivedEventArgs e)
		{
			byte[] bytes = e.Bytes;

			string text = new String(System.Text.Encoding.UTF8.GetChars(bytes));

			Debug.Print(text);
		}
	}
}


#4 Robert Hugo

Robert Hugo

    Advanced Member

  • Members
  • PipPipPip
  • 35 posts

Posted 25 May 2015 - 02:50 AM

Sample snippet for a Windows (8.1) Universal app (inject into a XAML .cs file):

		Universal.Udp.Cast cast;

		protected override void OnNavigatedTo(NavigationEventArgs e)
		{
			cast = new Universal.Udp.Cast(new Universal.Udp.EndPoint(new Windows.Networking.HostName("224.5.6.7"), "4567"));

			cast.DataReceived += Cast_DataReceived;

			cast.SendDataAsync(System.Text.Encoding.UTF8.GetBytes("Hello World!"));
		}

		protected override void OnNavigatingFrom(NavigatingCancelEventArgs e)
		{
			cast.DataReceived -= Cast_DataReceived;

			cast.Dispose();
		}

		async void Cast_DataReceived(object sender, Universal.Udp.Cast.DataReceivedEventArgs e)
		{
			string text = new string(System.Text.Encoding.UTF8.GetChars(e.Bytes));

			await this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
			{
				string s = "<" + e.Remote.ToString() + "> " + '"' + text + '"';

				textBlockOutput.Text += s + "\r\n";
			});
		}

		// E.g. for event Click of send Button.
		private void EventSend(object sender, RoutedEventArgs e)
		{
			byte[] bytes = System.Text.Encoding.UTF8.GetBytes("App: " + textBoxInput.Text);

			textBoxInput.Text = string.Empty;

			cast.SendDataAsync(bytes);

			textBoxInput.Focus(Windows.UI.Xaml.FocusState.Programmatic);
		}





0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users

home    hardware    projects    downloads    community    where to buy    contact Copyright © 2016 Wilderness Labs Inc.  |  Legal   |   CC BY-SA
This webpage is licensed under a Creative Commons Attribution-ShareAlike License.