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
    }
}

Category: Silverlight | Other Posts: View all posts by this blogger | Report as irrelevant | View bloggers stats | Views: 2906 | Hits: 34

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