(X) Hide this
    • Login
    • Join
      • Generate New Image
        By clicking 'Register' you accept the terms of use .

SocketsLight - Silverlight Sockets Framework

(7 votes)
Alexey Zakharov
>
Alexey Zakharov
Joined Sep 25, 2008
Articles:   8
Comments:   5
More Articles
21 comments   /   posted on May 28, 2009
Tags:   sockets , networking , json , alexey-zakharov
Categories:   General

This article is compatible with the latest version of Silverlight.


1. Introduction

Currently Silverlight supports two ways of duplex communication: sockets and WCF polling duplex services. I was really impressed by the simplicity of using WCF polling duplex in Silverlight, but its responsiveness and scalability leaves much to be desired. On the opposite site we have sockets, which are rather tricky to use, but their responsiveness and scalability satisfy real world application requirements.

In this article I’m going to introduce my SocketsLight framework, which should simplify the working with sockets by providing high level API over .NET sockets library.

Download source code

2. Content

2.1 Problem

As you know sockets have rather low level API, which allows you to transfer byte arrays frames using TCP. Working with them is not simple and error-prone, that is why I have decided to create lightweight framework, which would hide all complexity and provide similar message oriented API like that we have in polling duplex.

2.2 Solution

My SocketsLight framework provides a set of classes, which encapsulate byte array frames communication behavior. It automatically serializes user defined message objects and then split them into byte array frames, which would be transferred using sockets. The next picture illustrates the fundamental idea on which the library is based.

2.3 How it works

The whole framework is divided into client (Silverlight class library) and server (.NET class library) parts.

On the server side you will mostly deal with IMessageServer and IMessageSerializer interfaces and their implementations MessagerServer and JsonMessageSerializer. I strongly recommend you to only use interfaces and inject implementations in application bootstrapper with your favorite DI container.

IMessageServer informs you, when a client has connected or disconnected or a new message has been received, and provides a method to send message to the client with specified identifier (Guid).

IMessageSerializer defines how a message will be serialized. Currently there is only one implementation of this interface based on DataContractJsonSerializer. I found JSON format most effective and compact for this purpose, but you can easily create your own. I’ve also tried DataContractSerialzier and XmlSerializer, but its serialized message size is much bigger.

All message classes should be inherited from base Message class (empty class, used to identify that an object is a message) and be decorated with DataContract and DataMembers attributes, which is needed for .NET DataContract serializes.

On the client side you also need IMessageSerializer and another interface called IMessageClient and their implementations DataContractJsonSerializer and MessageClient. As for server side classes you should also use interfaces instead of implementations.

IMessageClient provides a set of methods to connect and disconnect to the message server, send and receive messages. It also informs if the connection with the server has been lost.

 

3. Example

In this example I will create a simple weather service, which will supply temperature info to its subscribers.

Weather service.

To use SocketLight framework we will inject IMessageServer through the constructor of our weather service and subscribe on its events. I’ve also created Timer object, which will invoke weather update on each 5 second.

 public WeatherService(IMessageServer messageServer)
 {
      this.messageServer = messageServer;
      this.messageServer.ClientConnected += this.messageServer_ClientConnected;
      this.messageServer.ClientDisconnected += this.messageServer_ClientDisconnected;
      this.messageServer.MessageRecieved += this.messageServer_MessageRecieved;
  
      this.updateTimer = new Timer(this.UpdateWeather, null, 0, 5000);
 }

To store service clients I will use dictionary: Key is client identifier (Guid), which is automatically set by message server after client connection, and Value is Subscriber class, which stores info about weather subscriber city. The adding and removing of clients will be performed during ClientConnected and ClientDisconnected events.

 private void messageServer_ClientConnected(object sender, ClientStatusChangedEventArgs e)
 {
     this.subscribers.Add(e.ClientId, new Subscriber());
 }
  
 private void messageServer_ClientDisconnected(object sender, ClientStatusChangedEventArgs e)
 {
     this.subscribers.Remove(e.ClientId);
 }

To set up weather subscriber city I’ve created specific message - SubscriberMessage. When the weather service receives SubscriberMessage it finds specified subscriber (MessageRecievedEventArgs have ClientId property, which allows to identify the client who has sent the message) and changes its city property.

 [DataContract]
 public class SubscribeMessage : Message
 {
     [DataMember]
     public string City { get; set; }
 }
 private void messageServer_MessageRecieved(object sender, MessageRecievedEventArgs e)
 {
     if (e.Message is SubscribeMessage)
     {
         var message = (SubscribeMessage)e.Message;
         if (this.subscribers.ContainsKey(e.ClientId))
         {
             this.subscribers[e.ClientId].City = message.City;
         }
      }
 }

As I said before I have created timer, which will invoke method for updating weather information on each 5 seconds. In this method I loop through all existing weather subscribers and if their city property is not null I send them the weather forecast for their city. For transferring weather data I have created WeatherMessage class, which holds information about the temperature in the weather subscriber’s city.

 [DataContract]
 public class WeatherMessage : Message
 {
     [DataMember]
     public int Temperature { get; set; }
 }
 private void UpdateWeather(object state)
 {
     var random = new Random();
  
     foreach (var weatherData in this.weather)
     {
         weatherData.Value.Temperature = random.Next(-30, 30);
     }
  
     foreach (var subscriber in this.subscribers)
     {
         if (subscriber.Value.City != null)
         {
             if (this.weather.ContainsKey(subscriber.Value.City))
             {
                 this.messageServer.SendMessageToClient(
                     subscriber.Key,
                     new WeatherMessage() { Temperature = this.weather[subscriber.Value.City].Temperature });
             }
         }
     }
 }

Finally, to start the weather service we should perform the following actions during ApplicationStart event:

1. Start policy server, which is used to provide clientaccesspolicy.xml file to the client to enable remote access.

2. Create instance of JsonMessageSerializer and supply all message types to it.

3. Inject JsonMessageSerializer to MessageServer constructor and start it.

4. Create instance of Weather service.

Be sure that you have started policy and message servers on the new threads, otherwise you may get serious performance problems.

 public class Global : System.Web.HttpApplication
 {
  
     protected void Application_Start(object sender, EventArgs e)
     {
         PolicyServer policyServer = new PolicyServer("clientaccesspolicy.xml");
         IMessageServer messageServer = new MessageServer(
             IPAddress.Any,
             4530,
             new JsonMessageSerializer(new List<Type>() { typeof(WeatherMessage), typeof(SubscribeMessage) }));
  
         ThreadPool.QueueUserWorkItem((o) => {policyServer.Start(); });
         ThreadPool.QueueUserWorkItem((o) => { messageServer.Start(); });
  
         WeatherService weatherService = new WeatherService(messageServer);
     }
 }

Also I want to point out that you can use single message server for different services. Just inject the same instance of message server to a different service.

Weather client.

For simplicity, in this example I won't create a specific class which will encapsulate weather client logic and will perform all actions in the code behind of Silverlight web form.

First of all we should create IMessageClient (Don’t forget to supply the same port number to message client and message server constructor), connect it to message server and subscribe on message received event. Message client events are invoked on non-UI threads that’s why you should Dispatcher BeginInvoke method if you need to bind something to UI.

 public MainPage()
 {
     this.InitializeComponent();
  
     this.messageClient = new MessageClient(
        4530, new JsonMessageSerializer(new List<Type>() { typeof(WeatherMessage), typeof(SubscribeMessage) }));
  
     this.messageClient.MessageRecieved += this.messageClient_MessageRecieved;
     this.messageClient.ConnectCompleted +=
         (s, args) => { 
              this.Dispatcher.BeginInvoke(() => { this.SubscribeButton.IsEnabled = true; }); 
         };
     this.messageClient.ConnectAsync();
 }
   
 private void messageClient_MessageRecieved(object sender, MessageRecievedEventArgs e)
 {
      if (e.Message is WeatherMessage)
      {
          var message = (WeatherMessage)e.Message;
          this.Dispatcher.BeginInvoke(() => { this.Temperature.Text = message.Temperature.ToString(); });
      }
 }

To subscribe on weather you should simply send SubscriberMessage with specified city.

 private void Subscribe_Click(object sender, RoutedEventArgs e)
 {
     this.messageClient.SendMessageAsync(
         new SubscribeMessage() { City = ((ComboBoxItem)this.CityComboBox.SelectedItem).Content.ToString() });
 }

4. Summary

Some of the ideas described in this article have been already blogged or written in some books, but there is still no reliable library, which unites them all together. I hope that this library would attract other developers and together we could make robust solution, which will make socket development as easy as possible. Currently it is in alpha version. Soon I’m going to refactor it and add more complex examples. And surely You are always welcome to contribute! 

Also I’m still looking forward at Silverlight WCF polling duplex services. I’ve already learnt much about its issues. Some of them you will find on my blog. But I’m sure that they will never be so responsive as sockets.

5. Links

Here are some useful links, which will be a good start to learn more about sockets.

1. Full implementation of a Silverlight Policy Server by Mike Snow.

2. TCP/IP Sockets in C#: Practical Guide for Programmers by David Makofske


Subscribe

Comments

  • -_-

    RE: SocketsLight - Silverlight Sockets Framework


    posted by Fabio Kaminski on May 28, 2009 11:59

    Nice Project!

    it may become a very helpful tool when the perfomance may be an issue.

    i doubt WCF polling duplex could be more optimized than that, with that tons  of protocol implementation.

    is this working just over http connection?

    im asking this cause when firewall and proxy´s may become present, we could have connection problems.

    and if it is (by the Timer logic it look that it does), there is a possiblity to create a duplex logic with a always connected port (Dont care about firewall blocking) other than http port( http keep-alive or non-http protocol at all) ?

    thanks and congratulations!

     

  • -_-

    RE: SocketsLight - Silverlight Sockets Framework


    posted by Alexey on May 28, 2009 12:35

    >> is this working just over http connection? 

    It uses tcp protocol

    >> and if it is (by the Timer logic it look that it does), there is a possiblity to create a duplex logic with a always connected port >> (Dont care about firewall blocking) other than http port( http keep-alive or non-http protocol at all) ?

    Timer is not used for polling. Timer is used in weather example to invoke server method which would broadcast message with new random weather data.
  • -_-

    RE: SocketsLight - Silverlight Sockets Framework


    posted by Lixin on May 28, 2009 20:52
    Good work!

    It is very useful when you try to push something from an application running in full trust mode into your Silverlight application. I have been using sockets to do so in the past one year but I have to say the SocketsLight framework can really simplify the coding and make development efficient.

    Thanks.


  • -_-

    RE: SocketsLight - Silverlight Sockets Framework


    posted by odanvin on Jun 20, 2009 20:56

    First of all thanks you for this added value on the sockets. I just want to share reconnection capabilities in case of lost connections. It could happen during web application recycling for example. In this case the messageServer just have to send a Message to all clients before it stops in the Application_End method of the Global.asax.cs. Then clients will be able to raise the ConnectionLost event and try to reconnect. Find below my the added feature on the MessageClient:

    // --------------------------------------------------------------------------------------------------------------------  
    // <copyright file="MessageClient.cs" company="Alexey Zakharov">  
    //   This file is part of SocketsLight Framework.  
    //  
    //   SocketsLight Framework is free software: you can redistribute it and/or modify  
    //   it under the terms of the GNU General Public License as published by   
    //   the Free Software Foundation, either version 3 of the License, or   
    //   (at your option) any later version.   
    //     
    //   SocketsLight Framework is distributed in the hope that it will be useful,   
    //   but WITHOUT ANY WARRANTY; without even the implied warranty of   
    //   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   
    //   GNU General Public License for more details.   
    //     
    //   You should have received a copy of the GNU General Public License   
    //   along with Foobar.  If not, see http://www.gnu.org/license.  
    // </copyright> 
    // <summary> 
    //   Defines the MessageClient type.  
    // </summary> 
    // --------------------------------------------------------------------------------------------------------------------  
     
    namespace Witcraft.SocketsLight.Client  
    {  
        using System;  
        using System.Collections.Generic;  
        using System.ComponentModel;  
        using System.Linq;  
        using System.Net;  
        using System.Net.Sockets;  
        using System.Windows;  
     
        using Witcraft.SocketsLight.Server;  
    using System.Windows.Threading;  
        using System.Diagnostics;  
        using System.Threading;  
        using System.Windows.Browser;  
     
        /// <summary> 
        /// Send and recives messages.  
        /// </summary> 
        public class MessageClient : IMessageClient  
        {  
            /// <summary> 
            /// Used to aggregate message frames.  
            /// </summary> 
            private List<byte> messageBuffer = new List<byte>();  
     
            /// <summary> 
            /// Serialize and deserialize messages.  
            /// </summary> 
            private IMessageSerializer messageSerializer;  
     
            /// <summary> 
            /// Port which will be used for message transfer.  
            /// </summary> 
            private int port;  
     
            /// <summary> 
            /// Socket which will be used for message transfer.  
            /// </summary> 
            private Socket socket;  
     
            /// <summary> 
            /// Dispatcher enabling code execution on UI thread.  
            /// </summary> 
            private Dispatcher dispatcher;  
     
            /// <summary> 
            /// Web client attempting connection re-establishment.  
            /// </summary> 
            private WebClient reconnectClient;  
     
            /// <summary> 
            /// Timer controlling the connection re-establishment.  
            /// </summary> 
            private Timer reconnectTimer;  
     
            /// <summary> 
            /// Date and time when connection re-establishment starts.   
            /// </summary> 
            private DateTime reconnectTime;  
     
            /// <summary> 
            /// Period between each connection re-establishment attempt.  
            /// </summary> 
            private TimeSpan reconnectPolling;  
     
            /// <summary> 
            /// Period during connection re-establishment are attempted.  
            /// </summary> 
            private TimeSpan reconnectTimeout;  
     
            /// <summary> 
            /// Initializes a new instance of the <see cref="MessageClient"/> class.  
            /// </summary> 
            /// <param name="port">  
            /// </param> 
            /// <param name="messageSerializer">  
            /// </param> 
            public MessageClient(int port, IMessageSerializer messageSerializer)  
                : this(port, messageSerializer, null)  
            {  
            }  
     
     
            /// <summary> 
            /// Initializes a new instance of the <see cref="MessageClient"/> class.  
            /// </summary> 
            /// <param name="port">The port.</param> 
            /// <param name="messageSerializer">The message serializer.</param> 
            /// <param name="dispatcher">The dispatcher.</param> 
            public MessageClient(int port, IMessageSerializer messageSerializer, Dispatcher dispatcher)  
            {  
                this.port = port;  
                this.messageSerializer = messageSerializer;  
                this.socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);  
                  
                this.dispatcher = dispatcher;  
                this.reconnectPolling = TimeSpan.FromSeconds(5);  
                this.reconnectTimeout = TimeSpan.FromSeconds(30);  
                this.reconnectClient = new WebClient();  
                this.reconnectClient.DownloadStringCompleted += new DownloadStringCompletedEventHandler(ReconnectClient_DownloadStringCompleted);  
            }  
     
     
            /// <summary> 
            /// Prevents a default instance of the <see cref="MessageClient"/> class from being created.  
            /// </summary> 
            private MessageClient()  
            {  
            }  
              
            /// <summary> 
            /// Occurs when client has connected to message server  
            /// </summary> 
            public event EventHandler<AsyncCompletedEventArgs> ConnectCompleted;  
     
            /// <summary> 
            /// Occure if connection with message server has been lost.  
            /// </summary> 
            public event EventHandler<EventArgs> ConnectionLost;  
     
            /// <summary> 
            /// Occurs when new message have been recieved.  
            /// </summary> 
            public event EventHandler<MessageRecievedEventArgs> MessageRecieved;  
     
            /// <summary> 
            /// Occurs when message is sent  
            /// </summary> 
            public event EventHandler<AsyncCompletedEventArgs> SendCompleted;  
     
            /// <summary> 
            /// Indicates if client is connected to message server.  
            /// </summary> 
            public bool Connected  
            {  
                get  
                {  
                    return this.socket.Connected;  
                }  
            }  
     
            /// <summary> 
            /// Connect to message server async.  
            /// </summary> 
            /// <param name="state">  
            /// </param> 
            public void ConnectAsync()  
            {  
                this.ConnectAsync(null);  
            }  
     
            /// <summary> 
            /// Connect to message server async.  
            /// </summary> 
            /// <param name="state">  
            /// </param> 
            public void ConnectAsync(object state)  
            {  
                if (!this.Connected)  
                {  
                    var endPoint = new DnsEndPoint(Application.Current.Host.Source.DnsSafeHost, this.port);  
                    var args = new SocketAsyncEventArgs { UserToken = stateRemoteEndPoint = endPoint };  
                    args.Completed += this.OnSocketConnected;  
                    this.socket.ConnectAsync(args);  
                }  
            }  
     
            /// <summary> 
            /// Reconnects to message server.  
            /// </summary> 
            private void Reconnect()  
            {  
                //start reconnect timer  
                reconnectTime = DateTime.Now;  
                Debug.WriteLine(string.Format("Connection re-establishment started at {0}", reconnectTime.ToString("o")));  
                this.reconnectTimer = new Timer(this.Reconnect  
                    , null  
                    , TimeSpan.Zero  
                    , reconnectPolling);  
            }  
     
            /// <summary> 
            /// Reconnects to message server.  
            /// </summary> 
            /// <param name="state">The state.</param> 
            private void Reconnect(object state)  
            {  
                //consider reconnect timeout  
                if ((DateTime.Now - reconnectTime) > reconnectTimeout)  
                    throw new TimeoutException(string.Format("Connection re-establishment failed since {0} and during {1}", reconnectTime, reconnectTimeout));  
     
                //skip web request call if previous request is still busy  
                if (!reconnectClient.IsBusy)  
                {  
                    Debug.WriteLine(string.Format("Connection re-establishment attempt at {0}", DateTime.Now.ToString("o")));  
                    dispatcher.BeginInvoke(() => 
                    {  
                        reconnectClient.DownloadStringAsync(HtmlPage.Document.DocumentUri);  
                    });  
                }  
            }  
     
            void ReconnectClient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)  
            {  
                if (e.Error == null)  
                {  
                    //stop reconnect timer  
                    reconnectTime = DateTime.MinValue;  
                    this.reconnectTimer.Dispose();  
     
                    //reconnect socket client  
                    dispatcher.BeginInvoke(() => 
                    {  
                        this.socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);  
                        this.ConnectAsync();  
                        Debug.WriteLine(string.Format("Connection re-established in {0}", (DateTime.Now - reconnectTime).ToString()));  
                    });  
                }  
            }  
     
            /// <summary> 
            /// Disconnect from message server.  
            /// </summary> 
            public void Disconnect()  
            {  
                this.socket.Close();  
            }  
     
            /// <summary> 
            /// Send message.  
            /// </summary> 
            /// <param name="message">  
            /// </param> 
            public void SendMessageAsync(Message message)  
            {  
                this.SendMessageAsync(message, null);  
            }  
     
            /// <summary> 
            /// Send message.  
            /// </summary> 
            /// <param name="message">  
            /// </param> 
            /// <param name="userState">  
            /// </param> 
            public void SendMessageAsync(Message message, object userState)  
            {  
                if ((this.socket == null) || (this.Connected == false))  
                {  
                    // TODO : throw exception.  
                }  
     
                var args = new SocketAsyncEventArgs();  
     
                byte[] serializedMessage = this.messageSerializer.Serialize(message);  
                List<byte> messageByteList = serializedMessage.ToList();  
     
                for (int i = 1023; i < serializedMessage.Length; i += 1023)  
                {  
                    messageByteList.Insert(i, 0);  
                    i++;  
                }  
     
                messageByteList.Add(1);  
     
                args.SetBuffer(messageByteList.ToArray(), 0, messageByteList.Count);  
                args.Completed += this.SocketSendCompleted;  
                args.UserToken = userState;  
     
                this.socket.SendAsync(args);  
            }  
     
            /// <summary> 
            /// </summary> 
            /// <param name="e">  
            /// </param> 
            private void OnConnected(AsyncCompletedEventArgs e)  
            {  
                EventHandler<AsyncCompletedEventArgs> handler = this.ConnectCompleted;  
                if (handler != null)  
                {  
                    handler(this, e);  
                }  
            }  
     
            /// <summary> 
            /// </summary> 
            /// <param name="e">  
            /// </param> 
            private void OnConnectionLost()  
            {  
                EventHandler<EventArgs> handler = this.ConnectionLost;  
                if (handler != null)  
                {  
                    handler(this, new EventArgs());  
                }  
            }  
     
            /// <summary> 
            /// </summary> 
            /// <param name="e">  
            /// </param> 
            private void OnMessageRecieved(MessageRecievedEventArgs e)  
            {  
                EventHandler<MessageRecievedEventArgs> handler = this.MessageRecieved;  
                if (handler != null)  
                {  
                    handler(this, e);  
                }  
            }  
     
            /// <summary> 
            /// </summary> 
            /// <param name="e">  
            /// </param> 
            private void OnSendCompleted(AsyncCompletedEventArgs e)  
            {  
                EventHandler<AsyncCompletedEventArgs> handler = this.SendCompleted;  
                if (handler != null)  
                {  
                    handler(this, e);  
                }  
            }  
     
            /// <summary> 
            /// </summary> 
            /// <param name="sender">  
            /// </param> 
            /// <param name="e">  
            /// </param> 
            private void OnSocketConnected(object sender, SocketAsyncEventArgs e)  
            {  
                AsyncCompletedEventArgs asyncArgs;  
                if (this.Connected)  
                {  
                    var response = new byte[1024];  
                    e.SetBuffer(response, 0, response.Length);  
                    e.Completed -this.OnSocketConnected;  
                    e.Completed += this.OnSocketReceive;  
     
                    this.socket.ReceiveAsync(e);  
                    asyncArgs = new AsyncCompletedEventArgs(null, false, e.UserToken);  
                    this.OnConnected(asyncArgs);  
                }  
     
                // TODO: Handle error while connection.  
            }  
     
            /// <summary> 
            /// </summary> 
            /// <param name="sender">  
            /// </param> 
            /// <param name="e">  
            /// </param> 
            private void OnSocketReceive(object sender, SocketAsyncEventArgs e)  
            {  
                if (e.BytesTransferred == 0)  
                {  
                    this.OnConnectionLost();  
                    this.socket.Close();  
                    //reconnect if possible  
                    if (dispatcher != null) this.Reconnect();  
                    return;  
                }  
     
                this.messageBuffer.AddRange(e.Buffer.Take(e.BytesTransferred - 1));  
                if (e.Buffer[e.BytesTransferred - 1] > 0)  
                {  
                    this.OnMessageRecieved(  
                        new MessageRecievedEventArgs(this.messageSerializer.Deserialize(this.messageBuffer.ToArray())));  
                    this.messageBuffer.Clear();  
                }  
     
                this.socket.ReceiveAsync(e);  
            }  
     
            /// <summary> 
            /// </summary> 
            /// <param name="sender">  
            /// </param> 
            /// <param name="e">  
            /// </param> 
            private void SocketSendCompleted(object sender, SocketAsyncEventArgs e)  
            {  
                if (e.SocketError == SocketError.Success)  
                {  
                    this.OnSendCompleted(new AsyncCompletedEventArgs(null, false, e.UserToken));  
                }  
     
                // TODO: Handle error if send is not successful.  
            }  
        }  
  • -_-

    RE: SocketsLight - Silverlight Sockets Framework


    posted by David Roh on Jun 30, 2009 12:26

    Thank you for sharing this Alexey,

    Communication optimization is a key feature in the success of many business applications - nice work.

    David

  • -_-

    RE: SocketsLight - Silverlight Sockets Framework


    posted by Alexey Zakharov on Jun 30, 2009 15:18
    >> odanvin

    Thanks for you comment. You'd better write about it at codeplex discussion section. Also I can provide you access to contribute to the project.


  • -_-

    RE: SocketsLight - Silverlight Sockets Framework


    posted by bob on Aug 18, 2009 14:04

    nice work Alex.

    i'm trying to create multi-player tic-tac-toe game using Silverlight 3.  can you supply some example how to use your code in such game?    thanks.

  • -_-

    RE: SocketsLight - Silverlight Sockets Framework


    posted by James Peckham on Dec 17, 2009 08:29
    simply awesome. thank you for this wonderful library.

    to 'bob': it comes with an example in the code... just check it out.
  • -_-

    RE: SocketsLight - Silverlight Sockets Framework


    posted by Peter Gfader on Feb 18, 2010 02:28

    VERY NICE work Alexey!!

    We are using sockets with Silverlight but the code is never tidy enough...

    Your implementation gave us a good direction where to go to...

    THANKS!

     

    .peter.gfader.

    http://peitor.blogspot.com/

    http://twitter.com/peitor

  • -_-

    RE: SocketsLight - Silverlight Sockets Framework


    posted by Eric on Mar 01, 2010 04:55

    I do not understand the following piece of the SendMessageAsync method of the MessageClient class.  I assume it has something to do with making the byteframe, but what does adding a 0 every 1024 bytes and a 1 at the very end do?

    byte[] serializedMessage = this.messageSerializer.Serialize(message);
    List<byte> messageByteList = serializedMessage.ToList();
      
    for (int i = 1023; i < serializedMessage.Length; i += 1023)
    {
         messageByteList.Insert(i, 0);
         i++;
    }
      
    messageByteList.Add(1);
  • -_-

    RE: SocketsLight - Silverlight Sockets Framework


    posted by peter on Apr 23, 2010 14:30

    some times when i use SendMessageAsync in loop to multi users the packet doesnt reach for some clients, when i put Thread.Sleep(300) before sending (in the loop) it work ok, but sometimes it happens again...., how can i be sure that the packets reach 100% ?

     

    thx,

    peter

  • -_-

    RE: SocketsLight - Silverlight Sockets Framework


    posted by Hu Bin on Jul 19, 2010 15:39

    VERY NICE work Alexey!!

    We are using sockets with Silverlight but the code is never tidy enough...

    Your implementation gave us a good direction where to go to...

    THANKS!

  • -_-

    RE: SocketsLight - Silverlight Sockets Framework


    posted by dejan on Aug 09, 2010 10:05

    Same issue as peter. By big objects  packets doesnt reach for some clients  ( > 20 packets  ) .

    thx,

    dejan

  • -_-

    RE: SocketsLight - Silverlight Sockets Framework


    posted by dejan on Aug 11, 2010 12:04

    There is some bugs.

    Now funct.

  • Armadous

    Re: SocketsLight - Silverlight Sockets Framework


    posted by Armadous on Aug 09, 2011 17:26

    This thing saved me a lot of time, mostly. I ran into an issue where clients were seemingly randomly receiving incomplete messages and throwing deserialization exceptions. What I thought was an issue with this project was actually a sleepy IIS problem.

     If you app has long lived clients and relatively infrequence web requests turn off IIS worker process idle timeout.

  • whittenizer

    Re: SocketsLight - Silverlight Sockets Framework


    posted by whittenizer on Sep 26, 2011 10:22

    Hi, I really like this framework. After working with Websockets for awhile, and having the need for multiple channels, I felt the need here as well. Maybe there is a way to achieve it with SocketsLite but I didnt see it.

    We could do such a thing using actions and having a property like a dictionary of actions with the key being a channel name. The client passes this dictionary of actions when subscribing to a channel. When sending any type of message(subscribe/publish/unsubscribe) we would pass in the channel name as a new property so we know which action to act on. The type of message will hold further context information to aid in calling the correct action.

    Has anyone achieved multiple channels anyother way?

    Thanks,

    David

  • sohummm

    Re: SocketsLight - Silverlight Sockets Framework


    posted by sohummm on Sep 30, 2011 20:38

    I believe the same problem exists on this as with my current socket-based implementation. As soon as you call ReceiveAsync after the connection is made (to listen for data from the server) you cannot use the UserToken to pass any useful information from the client and have it retained on the data reception.

    For example, if you have a handler you want to execute on the client-side after the data has been received, you won't be able to do that because the server response will be consumed by the ReceiveAsync that was called when the server connected, with the null UserToken.

  • rwhwilliam

    Re: SocketsLight - Silverlight Sockets Framework


    posted by rwhwilliam on Dec 07, 2011 07:33

    I got your example working.  I got the client to send messages to the server, and the server responds and sends a message back, but the client never receives it.  Any idea what could be causing this?

  • odanvin

    Re: SocketsLight - Silverlight Sockets Framework


    posted by odanvin on Jun 06, 2012 16:27
    I've recently improved this framework in order to support racing condition when several timers wake up at the same time to send socket messages. The current implementation does not support this scenario causing a deserialization issue client-side. More info below: http://socketslight.codeplex.com/discussions/358577
  • MahendraNiranjan

    Re: SocketsLight - Silverlight Sockets Framework


    posted by MahendraNiranjan on Aug 10, 2012 16:01

    In WeatherWidget Project, There are two file that has Up arrow icon on that.what is the meaning of Up arrow.

    I have seen files in  WeatherWidget project but Path of that Full Path is ...../WeatherService\SubscribeMessage.cs.

  • prithvi88

    Re: SocketsLight - Silverlight Sockets Framework


    posted by prithvi88 on Sep 18, 2013 12:01

    Hello All,

    I have one issue, I want to send user's basic information while user is connecting to server.

    e.g. this.messageClient.ConnectAsync(); // I want to send some user's information to server.

    So it is possible and if yes, then please help me I am stuck on this...


    Thanks in Advance

Add Comment

Login to comment:
  *      *