LAN上的Windows UWP Web服务发现

时间:2015-05-26 07:33:51

标签: c# web-services wcf windows-runtime win-universal-app

我正在尝试为本地网络上的客户端构建Web服务。对于服务,我可以针对任何版本的.NET Framework。客户端是移动Windows设备,我想使用通用Windows平台(UWP)作为目标框架。

该服务将在具有不同网络地址的多台计算机上运行。我的目标是客户端可以在连接到本地网络后立即自动检测服务。我想避免用户输入任何ip-address。但我能找到的所有样本都使用硬编码的服务URL。由于我没有DNS服务器,我必须将service-ip-address输入(或硬编码)到客户端。

目前我正在运行一个带有 UDPDiscoveryEndpoint 的WCF服务,这正是我想要的。但不幸的是,WCF的一部分( System.ServiceModel.Discovery 命名空间)在WinRT上不可用,并且在通用Windows平台上也不受支持。我不必使用WCF;任何具有服务发现功能的替代库都将是完美的。

所以这是我的问题:有没有办法在WinRT / UWP应用程序中的本地网络上进行服务发现?我尝试过ASP.NET Web API和SignalR,但似乎这个基于HTTP的服务/框架根本不支持发现。

谢谢!

2 个答案:

答案 0 :(得分:1)

我已经设法使用套接字和广播消息在UWP中进行webservice发现。

请注意,请查看my answer了解详情。

编辑 - 正如@ n​​aveen-vijay所说,我发布了一个更完整的aswer,而不仅仅是一个解决方案的链接。

每个WS都会侦听一个特定的端口,等待一些广播的消息搜索在LAN中运行的WS。 WS实现是win32,这是所需的代码:

private byte[] dataStream = new byte[1024];
private Socket serverSocket;
private void InitializeSocketServer(string id)
{
    // Sets the server ID
    this._id = id;
    // Initialise the socket
    serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
    // Initialise the IPEndPoint for the server and listen on port 30000
    IPEndPoint server = new IPEndPoint(IPAddress.Any, 30000);
    // Associate the socket with this IP address and port
    serverSocket.Bind(server);
    // Initialise the IPEndPoint for the clients
    IPEndPoint clients = new IPEndPoint(IPAddress.Any, 0);
    // Initialise the EndPoint for the clients
    EndPoint epSender = (EndPoint)clients;
    // Start listening for incoming data
    serverSocket.BeginReceiveFrom(this.dataStream, 0, this.dataStream.Length, SocketFlags.None, ref epSender, new AsyncCallback(ReceiveData), epSender);
}

private void ReceiveData(IAsyncResult asyncResult)
{
    // Initialise the IPEndPoint for the clients
    IPEndPoint clients = new IPEndPoint(IPAddress.Any, 0);
    // Initialise the EndPoint for the clients
    EndPoint epSender = (EndPoint)clients;
    // Receive all data. Sets epSender to the address of the caller
    serverSocket.EndReceiveFrom(asyncResult, ref epSender);
    // Get the message received
    string message = Encoding.UTF8.GetString(dataStream);
    // Check if it is a search ws message
    if (message.StartsWith("SEARCHWS", StringComparison.CurrentCultureIgnoreCase))
    {
        // Create a response messagem indicating the server ID and it's URL
        byte[] data = Encoding.UTF8.GetBytes($"WSRESPONSE;{this._id};http://{GetIPAddress()}:5055/wsserver");
        // Send the response message to the client who was searching
        serverSocket.BeginSendTo(data, 0, data.Length, SocketFlags.None, epSender, new AsyncCallback(this.SendData), epSender);
    }
    // Listen for more connections again...
    serverSocket.BeginReceiveFrom(this.dataStream, 0, this.dataStream.Length, SocketFlags.None, ref epSender, new AsyncCallback(this.ReceiveData), epSender);
}

private void SendData(IAsyncResult asyncResult)
{
    serverSocket.EndSend(asyncResult);
}

客户端实现是UWP。我创建了以下类来进行搜索:

public class WSDiscoveryClient
{
    public class WSEndpoint
    {
        public string ID;
        public string URL;
    }

    private List<WSEndpoint> _endPoints;
    private int port = 30000;
    private int timeOut = 5; // seconds

    /// <summary>
    /// Get available Webservices
    /// </summary>
    public async Task<List<WSEndpoint>> GetAvailableWSEndpoints()
    {
        _endPoints = new List<WSEndpoint>();

        using (var socket = new DatagramSocket())
        {
            // Set the callback for servers' responses
            socket.MessageReceived += SocketOnMessageReceived;
            // Start listening for servers' responses
            await socket.BindServiceNameAsync(port.ToString());

            // Send a search message
            await SendMessage(socket);
            // Waits the timeout in order to receive all the servers' responses
            await Task.Delay(TimeSpan.FromSeconds(timeOut));
        }
        return _endPoints;
    }

    /// <summary>
    /// Sends a broadcast message searching for available Webservices
    /// </summary>
    private async Task SendMessage(DatagramSocket socket)
    {
        using (var stream = await socket.GetOutputStreamAsync(new HostName("255.255.255.255"), port.ToString()))
        {
            using (var writer = new DataWriter(stream))
            {
                var data = Encoding.UTF8.GetBytes("SEARCHWS");
                writer.WriteBytes(data);
                await writer.StoreAsync();
            }
        }
    }

    private async void SocketOnMessageReceived(DatagramSocket sender, DatagramSocketMessageReceivedEventArgs args)
    {
        // Creates a reader for the incoming message
        var resultStream = args.GetDataStream().AsStreamForRead(1024);
        using (var reader = new StreamReader(resultStream))
        {
            // Get the message received
            string message = await reader.ReadToEndAsync();
            // Cheks if the message is a response from a server
            if (message.StartsWith("WSRESPONSE", StringComparison.CurrentCultureIgnoreCase))
            {
                // Spected format: WSRESPONSE;<ID>;<HTTP ADDRESS>
                var splitedMessage = message.Split(';');
                if (splitedMessage.Length == 3)
                {
                    var id = splitedMessage[1];
                    var url = splitedMessage[2];
                    _endPoints.Add(new WSEndpoint() { ID = id, URL = url });
                }
            }
        }
    }
}

答案 1 :(得分:0)

在UWP中,您可以使用PeerFinder类来发现LAN中应用程序的其他实例。

我知道这不完全是服务发现,它只是同行发现,但对于您的方案来说应该足够了。只需使用该应用程序的一个实例作为您的&#34;服务&#34;与其他实例通信。

您可以使用它来查找对等方并创建套接字连接:

$('#slider').slider().on('slideStop', function(ev){
    var newVal = $('#slider').data('slider').getValue();
    if(originalVal != newVal) {
         document.querySelector(".image-optimised").src="imgd.php?src=disco-ballin-corrected--05.jpg&quality="+newVal+"&w=500&h=500&cf";
           originalVal=newVal;
    }
});

要更深入地了解同伴发现的工作原理,请结帐this链接[分钟6:30]。