0

Let's say I have the following code running on a Windows service. I have to send data from a Windows service on a machine to a webpage that is open on the same machine(but not hosted on that machine).

        static void Main(string[] args)
        {
            Int32 counter = 0;
            while (counter < 100)
            {
                SendUDP("127.0.0.1", 49320, counter.ToString(), counter.ToString().Length);
                Thread.Sleep(2000);
                counter++;
            }
        }

        public static void SendUDP(string hostNameOrAddress, int destinationPort, string data, int count)
        {
            IPAddress destination = Dns.GetHostAddresses(hostNameOrAddress)[0];
            IPEndPoint endPoint = new IPEndPoint(destination, destinationPort);
            byte[] buffer = Encoding.ASCII.GetBytes(data);
            Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
            for (int i = 0; i < count; i++)
            {
                socket.SendTo(buffer, endPoint);
            }
            socket.Close();
            System.Console.WriteLine("Sent: " + data);
        }

I have to listen for the data sent to port 49320 and then process it in the browser.

I can create a listener on the webpage with Node.js like below, but I have to start this service separately and also install node.js on the client.

Is there any alternative to this? Something more lightweight ?

I could also create an AJAX to query a webservice every 2 seconds that would do the same thing as Windows Service, but it seems like a lot of queries sent all the time for nothing.

//websocket gateway on 8070
var app = require('http').createServer(handler)
  , io = require('socket.io').listen(app)
  , fs = require('fs');
var mysocket = 0;
app.listen(8070);
function handler (req, res) {
  fs.readFile(__dirname + '/index.html',
  function (err, data) {
    if (err) {
      res.writeHead(500);
      return res.end('Error loading index.html');
    }
    res.writeHead(200);
    res.end(data);
  });
}
io.sockets.on('connection', function (socket) {
  console.log('index.html connected'); 
  mysocket = socket;
});

//udp server on 49320
var dgram = require("dgram");
var server = dgram.createSocket("udp4");
server.on("message", function (msg, rinfo) {
  console.log("msg: " + msg);
  if (mysocket != 0) {
     mysocket.emit('field', "" + msg);
     mysocket.broadcast.emit('field', "" + msg);
  }
});
server.on("listening", function () {
  var address = server.address();
  console.log("udp server listening " + address.address + ":" + address.port);
});
server.bind(49320);
Dragos Durlut
  • 7,558
  • 10
  • 42
  • 57

1 Answers1

1

Use Signal R. This is a technology which automatically negotiates the most efficient transport for pushing events from a server to a browser (eg Forever Frames, Web Sockets) - it will fall back to the polling approach you mention in your question if required. I think this is a better approach to using raw UDP because all the low level work has been done for you.

Here's an example of using Signal R from a windows service: https://code.msdn.microsoft.com/windowsapps/SignalR-self-hosted-in-6ff7e6c3

From that sample - here's an even more simplified example of SignalR using OWIN to self host (without IIS):

using System;
using Microsoft.AspNet.SignalR;
using Microsoft.Owin.Cors;
using Microsoft.Owin.Hosting;
using Owin;

namespace SignalRWindowsService
{
    static class Program
    {
        static void Main()
        {
            string url = "http://localhost:8080";
            WebApp.Start(url);

            Console.WriteLine("Press any key to exit");
            Console.ReadKey();            
        }
    }

    class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            //This means you can access the web sockets from the local service (on a different URL) than the domain the page in the browser was served up from.
            app.UseCors(CorsOptions.AllowAll);
            app.MapSignalR();
        }
    }

    public class MyHub : Hub
    {
        public void Send(string name, string message)
        {
            Clients.All.addMessage(name, message);
        }
    }
}

You need the following NUGET packages:

<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="Microsoft.AspNet.Cors" version="5.0.0" targetFramework="net45" />
  <package id="Microsoft.AspNet.SignalR.Core" version="2.0.3" targetFramework="net45" />
  <package id="Microsoft.AspNet.SignalR.SelfHost" version="2.0.3" targetFramework="net45" />
  <package id="Microsoft.Owin" version="2.1.0" targetFramework="net45" />
  <package id="Microsoft.Owin.Cors" version="2.1.0" targetFramework="net45" />
  <package id="Microsoft.Owin.Diagnostics" version="2.0.1" targetFramework="net45" />
  <package id="Microsoft.Owin.Host.HttpListener" version="2.0.1" targetFramework="net45" />
  <package id="Microsoft.Owin.Hosting" version="2.0.1" targetFramework="net45" />
  <package id="Microsoft.Owin.Security" version="2.0.1" targetFramework="net45" />
  <package id="Microsoft.Owin.SelfHost" version="2.0.1" targetFramework="net45" />
  <package id="Newtonsoft.Json" version="5.0.1" targetFramework="net45" />
  <package id="Owin" version="1.0" targetFramework="net45" />
</packages>
Daniel James Bryars
  • 3,774
  • 1
  • 32
  • 52
  • Hello, I have tried using Signal R but I could not get it to start on my local computer. After that, I have tried to use Service Broker for MS SQL coupled with Microsoft Web Sockets, a tutorial found here: http://dejanstojanovic.net/aspnet/2014/june/database-change-notifications-in-aspnet-using-websocket/ Do you have any idea of the minimum requirements for IIS and windows version for WebSockets ? – Dragos Durlut Jun 22 '15 at 09:30
  • 1
    If you are using IIS for Web Sockets you'll need at least IIS 8.0 - it isn't supported in IIS 7 or 7.5 (http://www.iis.net/learn/get-started/whats-new-in-iis-8/iis-80-websocket-protocol-support). BUT I just tried the sample I mentioned in my answer and it works fine on my machine, I highly recommend you do that - the sample doesn't use IIS - it uses OWIN. I simplified the server to the minimum from the sample, and I'll update my answer with this code. – Daniel James Bryars Jun 22 '15 at 11:03
  • Thank you for your input, I have noticed though that WebSockets already uses SignalR. I have this in the console: SEC7118: XMLHttpRequest for http://localhost:55088/b7d452...f621a8ef6c1/arterySignalR/abort?transport=webSockets&connectionToken=AQAAANoAwE%2FCl%w%3D%3D&requestUrl=http%3A%2F%2Fdragosd%2FBroker01%2F&browserName=Internet+Explorer&userAgent=Mozilla%2F5.0+(Windows+NT+6.3%3B+WOW64%3B+Trident%2F7.0%3B+.NET4.0E%3B+.NET4.0C%3B+.NET+CLR+3.5.30729%3B+.NET+CLR+2.0.50727%3B+.NET+CLR+3.0.30729%3B+InfoPath.3%3B+rv%3A11.0)+like+Gecko required Cross Origin Resource Sharing (CORS). File: Broker01 – Dragos Durlut Jun 22 '15 at 12:38
  • 1
    You need to configure CORS - in the example I gave the line app.UseCors(CorsOptions.AllowAll); does this. Note, you can disable the browser security for debugging if you want to - here's how to do it in Chrome: http://stackoverflow.com/questions/3102819/disable-same-origin-policy-in-chrome – Daniel James Bryars Jun 22 '15 at 14:50
  • Thank you for your input, it has been of great help. I have noticed though that OWIN integrated iself into VS as, when I created a new project, it had OWIN integrated into the project. – Dragos Durlut Jun 23 '15 at 06:47