Silverlight 2 and Sockets

Posted by: Ajax.NET Professional, on 07 Mar 2008 | View original | Bookmarked: 0 time(s)

The new beta of Silverlight 2 introduces Sockets. The security model enforced by the System.Net.Sockets namespace in Silverlight 2 allows for a connection only back to the site or host of origin. So Silverlight 2 applications will be allowed to connect only to the host from which they were downloaded.

As the Web browser doesn't have a property of the IP address (as you may expect using sockets) there is a new endpoint class, the DnsEndPoint. To create a new instance of DnsEndPoint you have to specify the host name (as string e.g. from Application.Current.Host.Source.DnsSafeHost) and the port address.

 

string host = "mydomain.com";
int port = 80;
DnsEndPoint endPoint = new DnsEndPoint(host, port);

All methods of the Socket class to connect, send or receive have to be used asynchronous. I've created a small helper class that wraps all the asynchronous operations. You can download the C# source here.

 

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;

namespace Networking
{
    internal sealed class SocketClient : IDisposable
    {
        private const int Receive = 1;
        private const int Send = 0;

        private bool isConnected = false;

        private Socket socket;
        private DnsEndPoint endPoint;

        private static AutoResetEvent autoEvent = new AutoResetEvent(false);
        private static AutoResetEvent[] autoSendReceiveEvents = new AutoResetEvent[]
                {
                        new AutoResetEvent(false),
                        new AutoResetEvent(false)
                };

        internal SocketClient(string host, int port)
        {
            endPoint = new DnsEndPoint(host, port);
            socket = new Socket(AddressFamily.InterNetwork 
                        /* hostEndPoint.AddressFamily */, 
                        SocketType.Stream, ProtocolType.Tcp);
        }

        internal void Connect()
        {
            SocketAsyncEventArgs args = new SocketAsyncEventArgs();

            args.UserToken = socket;
            args.RemoteEndPoint = endPoint;
            args.Completed += new EventHandler<SocketAsyncEventArgs>(OnConnect);

            socket.ConnectAsync(args);
            autoEvent.WaitOne();

            if (args.SocketError != SocketError.Success)
                throw new SocketException((int)args.SocketError);
        }

        internal void Disconnect()
        {
            socket.Close();
        }

        #region Events

        private void OnConnect(object sender, SocketAsyncEventArgs e)
        {
            autoEvent.Set();
            isConnected = (e.SocketError == SocketError.Success);
        }

        private void OnReceive(object sender, SocketAsyncEventArgs e)
        {
            autoSendReceiveEvents[Send].Set();
        }

        private void OnSend(object sender, SocketAsyncEventArgs e)
        {
            autoSendReceiveEvents[Receive].Set();

            if (e.SocketError == SocketError.Success)
            {
                if (e.LastOperation == SocketAsyncOperation.Send)
                {
                    // Prepare receiving.
                    Socket s = e.UserToken as Socket;

                    byte[] response = new byte[255];
                    e.SetBuffer(response, 0, response.Length);
                    e.Completed += new EventHandler<SocketAsyncEventArgs>(OnReceive);
                    s.ReceiveAsync(e);
                }
            }
            else
            {
                ProcessError(e);
            }
        }

        #endregion

        private void ProcessError(SocketAsyncEventArgs e)
        {
            Socket s = e.UserToken as Socket;
            if (s.Connected)
            {
                try
                {
                    s.Shutdown(SocketShutdown.Both);
                }
                catch (Exception)
                {
                }
                finally
                {
                    if (s.Connected)
                        s.Close();
                }
            }

            throw new SocketException((int)e.SocketError);
        }

        internal String SendReceive(string message)
        {
            if (isConnected)
            {
                Byte[] bytes = Encoding.UTF8.GetBytes(message);

                SocketAsyncEventArgs args = new SocketAsyncEventArgs();
                args.SetBuffer(bytes, 0, bytes.Length);
                args.UserToken = socket;
                args.RemoteEndPoint = endPoint;
                args.Completed += new EventHandler<SocketAsyncEventArgs>(OnSend);

                socket.SendAsync(args);

                AutoResetEvent.WaitAll(autoSendReceiveEvents);

                return Encoding.UTF8.GetString(args.Buffer, args.Offset, args.BytesTransferred);
            }
            else
                throw new SocketException((int)SocketError.NotConnected);
        }

        #region IDisposable Members

        public void Dispose()
        {
            autoEvent.Close();
            autoSendReceiveEvents[Send].Close();
            autoSendReceiveEvents[Receive].Close();
            if (socket.Connected)
                socket.Close();
        }

        #endregion
    }
}

Advertisement
Free Agile Project Management Tool from Telerik
TeamPulse Community Edition helps your team effectively capture requirements, manage project plans, assign and track work, and most importantly, be continually connected with each other.
Category: Silverlight | Other Posts: View all posts by this blogger | Report as irrelevant | View bloggers stats | Views: 2022 | Hits: 33

Similar Posts

  • Silverlight bookshelf from SilverlightShow more
  • VS2010 is a game changer with WPF & Silverlight/WP7 Silverlight. more
  • What's new in RadControls for Silverlight Q3.2009 more
  • Using WCF with SQL Azure and Telerik OpenAccess more
  • View and print Reporting Services Reports from Silverlight. more
  • Silverlight Synchronicity more
  • Silverlight Audio Player for WordPress more
  • DevReach Follow-up, Part I more
  • Q3 2009 betas available now, Official release soon (update) more
  • RadControls for WPF/Silverlight Q3 Beta 2 release is live! more

News Categories

.NET | Agile | Ajax | Architecture | ASP.NET | BizTalk | C# | Certification | Data | DataGrid | DataSet | Debugger | DotNetNuke | Events | GridView | IIS | Indigo | JavaScript | Mobile | Mono | Patterns and Practices | Performance | Podcast | Refactor | Regex | Security | Sharepoint | Silverlight | Smart Client Applications | Software | SQL | VB.NET | Visual Studio | W3 | WCF | WinFx | WPF | WSE | XAML | XLinq | XML | XSD