将 UDP 数据从 Windows 服务发送到同一台机器上运行网页的浏览器

Posted

技术标签:

【中文标题】将 UDP 数据从 Windows 服务发送到同一台机器上运行网页的浏览器【英文标题】:Send UDP data from Windows Service to browser running webpage on same machine 【发布时间】:2015-06-21 18:07:19 【问题描述】:

假设我在 Windows 服务上运行以下代码。 我必须将数据从机器上的 Windows 服务发送到在同一台机器上打开的网页(但不是托管在该机器上)。

        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);
        

我必须监听发送到端口 49320 的数据,然后在浏览器中进行处理。

我可以使用 Node.js 在网页上创建一个监听器,如下所示,但我必须单独启动此服务并在客户端上安装 node.js。

有什么替代方案吗?更轻量级的东西?

我还可以创建一个 AJAX 来每 2 秒查询一次 Web 服务,这与 Windows 服务执行相同的操作,但似乎一直发送大量查询都是徒劳的。

//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);

【问题讨论】:

你考虑过在windows服务中使用SignalR吗? 【参考方案1】:

使用 Signal R。这是一种自动协商将事件从服务器推送到浏览器的最有效传输的技术(例如 Forever Frames、Web Sockets) - 如果出现问题,它将退回到您在问题中提到的轮询方法必需的。我认为这是使用原始 UDP 的更好方法,因为所有底层工作都已为您完成。

以下是使用 Windows 服务中的 Signal R 的示例: https://code.msdn.microsoft.com/windowsapps/SignalR-self-hosted-in-6ff7e6c3

来自该示例 - 这是 SignalR 使用 OWIN 进行自我托管(无 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);
        
    

您需要以下 NUGET 包:

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

【讨论】:

您好,我曾尝试使用 Signal R,但无法在本地计算机上启动它。之后,我尝试将 Service Broker for MS SQL 与 Microsoft Web Sockets 结合使用,这里有一个教程:dejanstojanovic.net/aspnet/2014/june/…你知道 WebSockets 的 IIS 和 windows 版本的最低要求吗? 如果您将 IIS 用于 Web Sockets,您至少需要 IIS 8.0 - IIS 7 或 7.5 (iis.net/learn/get-started/whats-new-in-iis-8/…) 不支持它。但是我刚刚尝试了我在回答中提到的示例,它在我的机器上运行良好,我强烈建议您这样做 - 该示例不使用 IIS - 它使用 OWIN。我将示例中的服务器简化到最低限度,我将使用此代码更新我的答案。 感谢您的意见,我注意到虽然 WebSockets 已经使用 SignalR。我在控制台中有这个:SEC7118: XMLHttpRequest for localhost:55088/b7d452...f621a8ef6c1/arterySignalR/… required Cross Origin Resource Sharing (CORS)。文件:Broker01 您需要配置 CORS - 在示例中,我给出了 app.UseCors(CorsOptions.AllowAll);做这个。请注意,如果您愿意,可以禁用浏览器安全性进行调试 - 以下是在 Chrome 中执行此操作的方法:***.com/questions/3102819/… 感谢您的意见,帮助很大。我注意到虽然 OWIN 将自己集成到 VS 中,但当我创建一个新项目时,它已将 OWIN 集成到项目中。

以上是关于将 UDP 数据从 Windows 服务发送到同一台机器上运行网页的浏览器的主要内容,如果未能解决你的问题,请参考以下文章

将 UDP 数据从 Python 发送到 Javascript?

Java将udp数据包发送到dns服务器

如何准备 UDP 数据报以发送到服务器

从同一个套接字发送和接收数据的简单 UDP 示例

UDP打孔:无法从服务器发送到客户端

发送和接收UDP数据[重复]