“Hello World” for .NET with Lightstreamer
by Alessandro AlinoneApril 14th, 2008After publishing the article “Hello World” with Lightstreamer, I received many requests to release a version of that tutorial for .NET developers. Therefore, in this installment we will work on a .NET port of the Java Data Adapter that we illustrated in the previous article. In particular, both a C# version and a Visual Basic version will be shown.
Let’s get started
First, please take a look at the previous installment, which provides some background and the general description of the application. Notice that the front-end will be exactly the same. We created a very simple HTML page that subscribes to the “greetings” item, using the “HELLOWORLD” Adapter. Now, we will replace the “HELLOWORLD” Adapter implementation based on Java with C# and Visual Basic equivalents. On the client side, nothing will change, as server side Adapters can be transparently switched and changed, as long as they respect the same interfaces. Thanks to this decoupling provided by Lightstreamer Server, we could even do something different. For example, we could keep the Java Adapter on the server side and use Flex, instead of HTML, on the client side. Or we could use the C# Adapter on the server side and use Java, instead of HMTL or Flex, on the client side. Basically, all the combinations of languages and technologies on the client side and on the server side are supported.
As in the previous installment, these examples will be based on Lightstreamer Server v. 3.4 and Lightstreamer Web Client v. 4.2.
Give me some .NET interfaces!
Lightstreamer Server is written in Java, so its native Adapter interfaces are Java based. The .NET interfaces are added through the Lightstreamer Adapter Remoting Infrastructure (ARI). Let’s have a look at it.

ARI is simply made up of two Proxy Adapters and a Network Protocol. The two Proxy Adapters implement the Java interfaces and are meant to be plugged into Lightstreamer Kernel, exactly as we did for our original “HELLOWORLD” Java Adapter. There are two Proxy Adapters because one implements the Data Adapter interface and the other implements the Metadata Adapter interface. Our “Hello World” example uses a default Metadata Adapter, so we only need the Proxy Data Adapter.
What does the Proxy Data Adapter do? Basically, it exposes the Data Adapter interface through TCP sockets. In other words, it offers a Network Protocol, which any remote counterpart can implement to behave as a Lightstreamer Data Adapter. This means you can write a remote Data Adapter in C, in PHP, or in COBOL, provided that you have access to very standard TCP sockets.
But—here is some magic—if your remote Data Adapter is based on .NET, you can forget about direct socket programming, and leverage a ready-made library that exposes a higher level .NET interface. So, you will simply have to implement this .NET interface. Ok, let’s recap… The Proxy Data Adapter converts from a Java interface to TCP sockets. The .NET library converts from TCP sockets to a .NET interface. Clear enough?
Creating the C# Data Adapter
Let’s start with C#. Feel free to skip this section if you are only interested in the Visual Basic example (I will replicate the same comments on the code).
We should implement two classes. One (which we will call DataAdapterLauncher) contains the application’s Main and initializes the DataProviderServer (the provided piece of code that implements the Network Protocol). The other (which we will call HelloWorldAdapter) implements the actual Adapter interface.
- Create a new C# project (I used Microsoft’s Visual C# 2008 Express Edition).
- From the “New Project…” wizard, choose the “Console Application” template. Let’s use “adapter_csharp” as the project name.
- From the “Solution Explorer”, delete the default Program.cs, then add a reference to the Lightstreamer .NET library: go to the “Browse” tab of the “Add Reference” dialog and point to the DotNetAdapter_N2.dll file, which you can find in the “Lightstreamer\DOCS-SDKs\sdk_adapter_dotnet\lib\dotnet_2.0″ folder of your Lightstreamer installation.
DataAdapterLauncher
Add a new class (let’s call its file DataAdapterLauncher.cs). Replace the source code with this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | using System; using System.Net.Sockets; using Lightstreamer.DotNet.Server; public class DataAdapterLauncher { public static void Main(string [] args) { string host= "localhost"; int reqrepPort = 6661; int notifPort = 6662; try { DataProviderServer server = new DataProviderServer(); server.Adapter = new HelloWorldAdapter(); TcpClient reqrepSocket = new TcpClient(host, reqrepPort); server.RequestStream = reqrepSocket.GetStream(); server.ReplyStream = reqrepSocket.GetStream(); TcpClient notifSocket = new TcpClient(host, notifPort); server.NotifyStream = notifSocket.GetStream(); server.Start(); System.Console.WriteLine("Remote Adapter connected to Lightstreamer Server."); System.Console.WriteLine("Ready to publish data..."); } catch (Exception e) { System.Console.WriteLine("Could not connect to Lightstreamer Server."); System.Console.WriteLine("Make sure Lightstreamer Server is started before this Adapter."); System.Console.WriteLine(e); } } } |
This code creates a DataProviderServer instance and assigns a HelloWorldAdapter instance (which we will define below) to it. Then, it creates two TCP client sockets, because the Proxy Data Adapter, to which our remote .NET Adapter will connect, needs two connections (but as I said, after creating these sockets, you don’t have to bother with reading and writing, as these operations are automatically handled by the DataProviderServer). Let’s use TCP ports 6661 and 6662. Assign the stream of the first socket to the RequestStream and ReplyStream properties of the DataProviderServer. Assign the stream of the second socket to the NotifyStream property of the DataProviderServer. Finally, you start the DataProviderServer.
HelloWorldAdapter
Now add another class (call its file HelloWorld.cs). Replace the source code with this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | using System; using System.Collections; using System.Threading; using Lightstreamer.Interfaces.Data; public class HelloWorldAdapter : IDataProvider { private IItemEventListener _listener; private volatile bool go; public void Init(IDictionary parameters, string configFile) { } public bool IsSnapshotAvailable(string itemName) { return false; } public void SetListener(IItemEventListener eventListener) { _listener = eventListener; } public void Subscribe(string itemName) { if (itemName.Equals("greetings")) { Thread t = new Thread(new ThreadStart(Run)); t.Start(); } } public void Unsubscribe(string itemName) { if (itemName.Equals("greetings")) { go = false; } } public void Run() { go = true; int c = 0; Random rand = new Random(); while (go) { IDictionary eventData = new Hashtable(); eventData["message"] = c % 2 == 0 ? "Hello" : "World"; eventData["timestamp"] = DateTime.Now.ToString("s"); _listener.Update("greetings", eventData, false); c++; Thread.Sleep(1000 + rand.Next(2000)); } } } |
The HelloWorldAdapter class implements the IDataProvider interface (which is the .NET remote equivalent of the Java DataProvider interface).
Implement the SetListener method to receive a reference to the server’s listener that you will use to inject events.
Then, implement the Subscribe method. When the “greetings” item is subscribed to by the first user, the Adapter receives that method call and starts a thread that will generate the real-time data. If more users subscribe to the “greetings” item, the Subscribe method is not called any more. When the last user unsubscribes from this item, the Adapter is notified through the Unsubscribe call. In this case we stop the publisher thread for that item. If a new user re-subscribes to “greetings”, the Subscribe method is called again. As already mentioned in the previous installment, this approach avoids consuming processing power for items nobody is currently interested in.
The Run method is executed within the thread started by Subscribe. Its code is very simple. We create a Hashtable containing a message (alternating “Hello” and “World”) and the current timestamp. Then we inject the Hashtable into the server through the listener. We wait for a random time between 1 and 3 seconds, and we are ready to generate a new event.
Save and build
From the File menu, choose “Save All“. Type a location, for example: “c:\”.
From the Build menu, choose “Build Solution“. Your C# Data Adapter is now compiled. If you used the path above, you will find your executable file under “C:\adapter_csharp\adapter_csharp\bin\Release”. It is called “adapter_csharp.exe“. But be patient and don’t start it now, because you have to configure and start the Lightstreamer Server first. You can skip the section below, dedicated to VB, and go straight to the “Deploy the Proxy Adapter” section.
Creating the Visual Basic Data Adapter
Now let’s work with Visual Basic instead of C#.
We will create a module (DataAdapterLauncher) which contains the application’s Main and initializes the DataProviderServer (the provided piece of code that implements the Network Protocol). Then we will create a class (HelloWorldAdapter) that implements the actual Adapter interface.
- Create a new VB project (I used Microsoft’s Visual Basic 2008 Express Edition).
- From the “New Project…” wizard, choose the “Console Application” template. Let’s use “adapter_vb” as the project name.
- From the “Solution Explorer”, delete the default Module1.vb, then add a reference to the Lightstreamer .NET library: go to the “Browse” tab of the “Add Reference” dialog and point to the DotNetAdapter_N2.dll file, which you can find in the “Lightstreamer\DOCS-SDKs\sdk_adapter_dotnet\lib\dotnet_2.0″ folder of your Lightstreamer installation.
DataAdapterLauncher
Add a new module (let’s call its file DataAdapterLauncher.vb). Replace the source code with this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | Imports System.Net.Sockets Imports Lightstreamer.DotNet.Server Module Module1 Sub Main() Dim host As String = "localhost" Dim reqrepPort As Integer = 6661 Dim notifPort As Integer = 6662 Try Dim server As New DataProviderServer() server.Adapter = New HelloWorldAdapter() Dim reqrepSocket As New TcpClient(host, reqrepPort) server.RequestStream = reqrepSocket.GetStream() server.ReplyStream = reqrepSocket.GetStream() Dim notifSocket As New TcpClient(host, notifPort) server.NotifyStream = notifSocket.GetStream() server.Start() System.Console.WriteLine("Remote Adapter connected to Lightstreamer Server.") System.Console.WriteLine("Ready to publish data...") Catch e As Exception System.Console.WriteLine("Could not connect to Lightstreamer Server.") System.Console.WriteLine("Make sure Lightstreamer Server is started before this Adapter.") System.Console.WriteLine(e) End Try End Sub End Module |
This code creates a DataProviderServer instance and assigns a HelloWorldAdapter instance (which we will define below) to it. Then, it creates two TCP client sockets, because the Proxy Data Adapter, to which our remote .NET Adapter will connect, needs two connections (but as I said, after creating these sockets, you don’t have to bother with reading and writing, as these operations are automatically handled by the DataProviderServer). Let’s use TCP ports 6661 and 6662. Assign the stream of the first socket to the RequestStream and ReplyStream properties of the DataProviderServer. Assign the stream of the second socket to the NotifyStream property of the DataProviderServer. Finally, start the DataProviderServer.
HelloWorldAdapter
Now add a class (call its file HelloWorld.vb). Replace the source code with this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | Imports System.Collections Imports System.Threading Imports Lightstreamer.Interfaces.Data Public Class HelloWorldAdapter Implements IDataProvider Private _listener As IItemEventListener Private go As Boolean Public Sub Init(ByVal parameters As IDictionary, ByVal configFile As String) Implements IDataProvider.Init End Sub Function IsSnapshotAvailable(ByVal itemName As String) As Boolean Implements IDataProvider.IsSnapshotAvailable Return False End Function Public Sub SetListener(ByVal eventListener As IItemEventListener) Implements IDataProvider.SetListener _listener = eventListener End Sub Public Sub Subscribe(ByVal itemName As String) Implements IDataProvider.Subscribe If itemName.Equals("greetings") Then Dim t As New Thread(AddressOf Run) t.Start() End If End Sub Public Sub Unsubscribe(ByVal itemName As String) Implements IDataProvider.Unsubscribe If itemName.Equals("greetings") Then go = False End If End Sub Public Sub Run() go = True Dim c As Integer = 0 Dim rand As New Random() While go Dim eventData As IDictionary = New Hashtable() eventData("message") = IIf(c Mod 2 = 0, "Hello", "World") eventData("timestamp") = DateTime.Now.ToString("s") _listener.Update("greetings", eventData, False) c += 1 Thread.Sleep(1000 + rand.Next(2000)) End While End Sub End Class |
The HelloWorldAdapter class implements the IDataProvider interface (which is the .NET remote equivalent of the Java DataProvider interface).
Implement the SetListener subroutine to receive a reference to the server’s listener that you will use to inject events.
Then, implement the Subscribe subroutine. When the “greetings” item is subscribed to by the first user, the Adapter receives that subroutine call and starts a thread that will generate the real-time data. If more users subscribe to the “greetings” item, the Subscribe subroutine is not called any more. When the last user unsubscribes from this item, the Adapter is notified through the Unsubscribe call. In this case we stop the publisher thread for that item. If a new user re-subscribes to “greetings”, the Subscribe subroutine is called again.
The Run subroutine is executed within the thread started by Subscribe. Its code is very simple. We create a Hashtable containing a message (alternating “Hello” and “World”) and the current timestamp. Then we inject the Hashtable into the server through the listener. We wait for a random time between 1 and 3 seconds, and we are ready to generate a new event.
Save and build
From the File menu, choose “Save All“. Type a location, for example: “c:\”.
From the Build menu, choose “Build adapter_vb“. Your VB Data Adapter is now compiled. If you used the path above, you will find your executable file under “C:\adapter_vb\adapter_vb\bin\Release”. It is called “adapter_vb.exe“. As for the C# Adapter, don’t start it now, because you have to configure and start the Lightstreamer Server first.
Deploying the Proxy Adapter
Now that our remote Data Adapter is ready, we need to deploy and configure the provided Proxy Adapter within Lightstreamer Server.
Go to the “adapters” folder of your Lightstreamer Server installation. You could already have a “StockList” folder (containing a pre-installed demo Adapter) and a “HelloWorld” Adapter (if you followed the Java tutorial of the previous installment). Now create a “ProxyHelloWorld” folder inside “adapters”, and a “lib” folder inside “ProxyHelloWorld”.
Copy the “ls-proxy-adapters.jar” file from “Lightstreamer/DOCS-SDKs/sdk_adapter_remoting_infrastructure/lib” to “Lightstreamer/adapters/ProxyHelloWorld/lib”.
Create a new file in “Lightstreamer/adapters/ProxyHelloWorld”, call it “adapters.xml“, and use the following contents:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <?xml version="1.0"?> <adapters_conf id="PROXY_HELLOWORLD"> <metadata_provider> <adapter_class>com.lightstreamer.adapters.metadata.LiteralBasedProvider</adapter_class> </metadata_provider> <data_provider> <adapter_class>com.lightstreamer.adapters.remote.data.NetworkedDataProvider</adapter_class> <param name="request_reply_port">6661</param> <param name="notify_port">6662</param> </data_provider> </adapters_conf> |
You have just deployed a new Java Adapter pair, where the Metadata Adapter is a default one (called “LiteralBasedProvider”) and the Data Adapter is the Proxy Adapter (called “NetworkedDataProvider”). This Adapter pair will be referenced by the clients as “PROXY_HELLOWORLD“.
As a final configuration, let’s tell our Web client to use this new Adapter pair, rather than those we developed last time. So just edit the “index.htm” page of the Hello World front-end (last time we deployed it under “Lightstreamer/pages/HelloWorld”) and replace:
engine.connection.setAdapterName("HELLOWORLD");
with:
engine.connection.setAdapterName("PROXY_HELLOWORLD");
Running the application
Now we have all the pieces ready. Let’s enjoy the results.
Start your Lightstreamer Server. When it’s up, run either the C# or the VB Remote Adapter.
Open a browser window and go to: http://localhost:8080/HelloWorld/
Final notes
Starting from these very simple code fragments we have developed in these two installments (covering basic JavaScript, Java, C#, and VB), I encourage you to experiment and create more complex applications. The full API references for all these languages are available from the links below:
- .NET API reference for Adapters (save and unblock this file from the Properties dialog)
- Java API reference for Adapters
- JavaScript API reference for Clients
All the source code described in this article is available for download.
As I already outlined in the previous installment, we used the free Moderato edition of Lightstreamer for this tutorial. Its main limitation, with respect to the commercial editions, is that it only allows 1 update/sec for each subscribed item (but you can subscribe to as many items as you want). If you need to experiment with higher-frequency events for the same item, you can use a free evaluation license of Lightstreamer Presto or Vivace.










May 26th, 2008 at 3:21 am
hello Alessandro, can you tell me the theory about the Lightstreamer interactionDemo for .net, i am very interest in it, thank you very much!
May 26th, 2008 at 8:28 pm
can you give me a small demo for the .net adapter?
June 25th, 2008 at 7:46 am
@jingye800: There are currently two public examples of .NET Lightstreamer Adapters. One is the “Hello World” example of this article. The other is the Stock List Demo, which you can find in any Lightstreamer distribution under the “Lightstreamer\DOCS-SDKs\sdk_adapter_dotnet\examples” folder.
If anybody else makes available any Adapter example, please let me know, so that it can be shared with the Lightstreamer community.
August 16th, 2008 at 7:30 pm
Dear Alessandro Alinone , Thanks very much for your great efferots , your article was very helpful and explain many concepts.
just one you may missed it to copy LS folder ( js ) to working directory of index.htm.
Could you please explain ( in another article ) how to creat client in VB desktop application?
is there is any example to show how?
your kind reply will be highly appreciated.
Thanks.
January 19th, 2009 at 2:04 am
Thank you for your nice article , but when i deployed the application & run it , i got the following alert error
“1:11:0:22,656 ER bind unable to find the engine .Retrying .If the problem persists , please check your configuration”
So, how can we solve it?
Thank You
January 19th, 2009 at 2:15 am
hello Alessandro,
can You tell me what is the solution for this alert which appears after i deployed the applicationand rub it
“4:11:11:28,796 ER createEngine The call of createEngine methods after the body onload event is supported only for DOM2 browsers.You might have reached this point , due to solw page downloads.”
Best Regards
March 2nd, 2009 at 1:22 am
Hi Alessadro,
Thank you for your nice article, but I get the following alert message when deploying the application and run it:
“1:11:0:57,257 ER bind unable to find the engine .Retrying .If the problem persists , please check your configuration”
I followed exactly the steps shown in the article, what does this error message means?
Thank you.
April 1st, 2009 at 5:26 am
Hi Alessadro,
Thanks for the article, but I also get the ‘ER bind Unable to find the Engine’ error.
Has anyone found a solution for it yet?
MK
April 3rd, 2009 at 7:01 am
Hi guys,
It seems you probably didn’t deploy the front-end resources correctly, as explained in the first article. Please make sure that the “Hello World” example explained in the first article works correctly, before moving to the .NET version (you don’t need to compile any Java code, as the first article provides the ready binaries too).
Typically, the “bind unable to find the engine” error happens when the createEngine() call does not specify the right path for the Lightstreamer libraries as the second parameter. In the example above, the call that you find inside index.htm is:
page.createEngine(”HelloWorldApp”, “LS”, “SHARE_SESSION”);
This means that in the folder containing index.htm, an “LS” folder must exist containing all the Lightstreamer libraries.
Hope that helps.
-Alessandro
April 22nd, 2009 at 7:39 am
Hi.
I’m following these instructions, but they seem to be incomplete.
The section “Deploying the Proxy Adapter” doesn’t mention what files from bin\Debug from the C# project need to be copied to the Lightstreamer\adapters\Proxy_HelloWorld folder.
I copied all anyway, restarted the server, updated index.htm to point to PROXY_HELLOWORLD, but I get a browser error “IE cannot display the page”.
Before this, I deployed the Java version of the adapter and started it successfully.
In the Lightstreamer.log file I see these entries that don’t seem to be completed:
22-Apr-09 07:16:27,828 |INFO |.remote.transport.SocketTransport|uest/Reply Socket Connector|Waiting for a connection on port 6661…
22-Apr-09 07:16:27,828 |INFO |.remote.transport.SocketTransport|Notify Socket Connector |Waiting for a connection on port 6662…
And these sentences from the C# project that should be displayed somewhere, I assume the log file, are nowhere to be seen:
System.Console.WriteLine(”Remote Adapter connected to Lightstreamer Server.”);
System.Console.WriteLine(”Ready to publish data…”);
Is LS server supposed to launch the adapter_csharp.exe program? At what point? If not, how is that program supposed to be started?
Finally, I removed the folder Proxy_HelloWorld from Lightstreamer\adapters on the server, restarted the server, changed the index.htm client page to point back to HELLOWORLD, and it works fine.
Could somebody explain how this proxy adapter is supposed to work, or how to make the demo run successfully?
Thanks in advance.
Guillermo
April 22nd, 2009 at 7:49 am
Reply to my previous posting:
Never mind. I started the console app manually and it all started working.
I’d still like to know what specific files from the C# project are supposed to be deployed in the adapters folder, whether the .exe and .dll files only or the .pdb as well.
Thanks for the demo. Nice job.
-Guillermo
May 7th, 2009 at 7:35 am
Guillermo,
As explained in the article, you must copy only “ls-proxy-adapters.jar” and “adapters.xml” in the “ProxyHelloWorld” folder inside the “adapters” folder.
June 17th, 2009 at 2:00 am
Hi, thank you for this article it’s very helpfull
I wanna build web chat application using lightstreamer and ASP.NET..can you help with the architecture. How will Lightstreamer work along the asp.net server..etc
Thanks
September 15th, 2009 at 12:11 am
Hi all
Thank you for your nice article, but I get the following alert message when deploying the application and run it:
“1:11:0:57,257 ER bind unable to find the engine .Retrying .If the problem persists , please check your configuration”
Help me
September 16th, 2009 at 12:35 am
Help
“1:11:0:57,257 ER bind unable to find the engine .Retrying .If the problem persists , please check your configuration”
October 9th, 2009 at 2:45 pm
Hi,
It’s easier if you post any questions to the Lightstreamer forums, to take benefit of thread-based organizations: http://www.lightstreamer.com/forum
October 29th, 2009 at 11:44 am
I have built the adapter_csharp but the I start lightstremaer using the start LS as application batch file, the file hangs at the end saying
waiting for a connection on port 6662…
waiting for a connection on port 6661…
and the port 8080 server does not start.
But if I manually run the adapter_csharp.exe in the lib folder the lightstreamer comes alive and does work. Why doesn’t the .exe load itself - do I have to set the startup object in the project configuration??
Thanks
October 29th, 2009 at 11:59 am
Follow up - I seem to have the same issue as Guillermo above, I have to start csharp_adapter.exe manually while the start LS as application.bat file is waiting
November 16th, 2009 at 4:30 am
Answered here: http://www.lightstreamer.com/vb/showthread.php?t=608