UWP 应用中的 WCF 发现 [英] WCF discovery in UWP app

查看:23
本文介绍了UWP 应用中的 WCF 发现的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个通用应用程序,可以连接到 Intranet 上的 WCF 网络服务,它运行良好,因为服务主机的地址是已知的.

I've created an universal app that connects to a WCF webservice at intranet, an it's working just fine, since the address of the service's host is known.

出于性能和安全(冗余)的原因,系统的架构允许在不同的主机上运行多个网络服务.因此,我试图让我的应用发现在给定合同下运行在同一 LAN 上的每项服务,但我无法做到这一点.

The system's architecture allows to be more than one webservice running, in different hosts, for performance and security (redundancy) reasons. So I'm trying to make my app discover every service, with the given contract, that is been running on the same LAN, but I can't manage to do that.

我正在尝试在非常相似的 win32 应用程序中使用的相同方法:

I'm trying the same approach used at a very similar win32 app:

var discoveryClient = new DiscoveryClient(new UdpDiscoveryEndpoint());
var findCriteria = new FindCriteria(typeof(INewProdColetorWCFService));
findCriteria.Duration = TimeSpan.FromSeconds(5);
var findResponse = await discoveryClient.FindTaskAsync(findCriteria);

Visual Studio自动"为我添加所需的参考(System.ServiceModel.Discovery)如所见这里

Visual Studio "automatically" adds the needed reference (System.ServiceModel.Discovery) for me as seen here

在设计时似乎没问题,但是当我尝试编译时,出现该错误:

At design time it seems to be ok, but when i try to compile, that error appear:

在 System.ServiceModel.dll 模块中找不到类型 System.ServiceModel.Configuration.ServiceModelConfigurationElementCollection`1.

Cannot find type System.ServiceModel.Configuration.ServiceModelConfigurationElementCollection`1 in module System.ServiceModel.dll.

你们中有人在 UWP 中做过吗?你能帮助我吗?提前致谢,iuri.

Have any of you did that in UWP? Can you help me? Thanks in advance, iuri.

ps:我已经发布了MSDN 中的这个问题 也是

推荐答案

我不知道我是否应该回答我自己的问题,但我认为它可能对任何尝试做同样事情的人有用,所以就这样吧.

I don't know if I should answer my own question, but I think it may be useful for anyone trying to do the same, so here it goes.

由于 WS-Discovery API 在 UWP 中不可用,我不得不以另一种方式来实现.使用 socket 是我能找到的最好的选择.所以每个 WS 都会监听一个特定的端口,等待一些广播消息搜索在 LAN 中运行的 WS.

Since WS-Discovery API is not available in UWP, I had to do it in another way. Using socket was the best alternative I could find. So every WS will listen to a specific port, awaiting for some broadcasted message searching for WS running in the LAN.

WS 实现是 win32,这是需要的代码:

The WS implementation is win32, and this is the code needed:

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.我创建了以下类来进行搜索:

The client implementation is UWP. I've created the following class to do the search:

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

如果您发现不对的地方,请随时发表评论,如果对您有所帮助,请告诉我.

Feel free to comment if you see something wrong, and please tell me if it helps you someway.

这篇关于UWP 应用中的 WCF 发现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆