c# - UWP 应用中的 WCF 发现

标签 c# wcf uwp ws-discovery

我创建了一个连接到 Intranet 上的 WCF Web 服务的通用应用程序,它工作得很好,因为服务主机的地址是已知的。

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

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

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) as seen here

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

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

你们有人在 UWP 中这样做过吗?你能帮助我吗? 预先感谢,iuri。

ps:我已发布this question in MSDN也是

最佳答案

我自己做一些研究时发现了这个帖子。阅读 https://en.wikipedia.org/wiki/WS-Discovery 后并使用 Wireshark 破译一些细节,我得到了支持 Microsoft WS-Discovery 规范的基本概念证明,这意味着服务器端无需进行任何更改。

我现在已经退出了这个项目,但希望有人能从中得到一些用处:

public class WSDiscoveryResponse
{
    private readonly string
        _content,
        _remotePort;

    private readonly HostName
        _remoteAddress;

    public WSDiscoveryResponse(string content, HostName remoteAddress, string remotePort)
    {
        this._content = content;
        this._remoteAddress = remoteAddress;
        this._remotePort = remotePort;
    }
}

public class WSDiscoveryClient
{
    private const string
        SRC_PORT = "0",//represents 'use any port available'
        DEST_IP_WSDISCOVERY = "239.255.255.250", //broadcast (ish)
        DEST_PORT_WSDISCOVERY = "3702";

    private TimeSpan _timeout = TimeSpan.FromSeconds(5);

    private List<WSDiscoveryResponse> _wsresponses = null;

    /// <summary>
    /// Get available Webservices
    /// </summary>
    public async Task<List<WSDiscoveryResponse>> GetAvailableWSEndpoints()
    {
        _wsresponses = new List<WSDiscoveryResponse>();
        using (var socket = new DatagramSocket())
        {
            try
            {
                socket.MessageReceived += SocketOnMessageReceived;
                //listen for responses to future message
                await socket.BindServiceNameAsync(SRC_PORT);
                //broadcast interrogation
                await SendDiscoveryMessage(socket);
                //wait for broadcast responses
                await Task.Delay(_timeout).ConfigureAwait(false);
            }
            catch (Exception ex)
            {
                SocketErrorStatus webErrorStatus = SocketError.GetStatus(ex.GetBaseException().HResult);
            }
        }
        return _wsresponses;
    }

    private string BuildDiscoveryMessage()
    {
        const string outgoingMessageFormat = @"<s:Envelope xmlns:s=""http://www.w3.org/2003/05/soap-envelope"" xmlns:a=""http://www.w3.org/2005/08/addressing""><s:Header><a:Action s:mustUnderstand=""1"">http://docs.oasis-open.org/ws-dd/ns/discovery/2009/01/Probe</a:Action><a:MessageID>urn:uuid:{0}</a:MessageID><a:ReplyTo><a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address></a:ReplyTo><a:To s:mustUnderstand=""1"">urn:docs-oasis-open-org:ws-dd:ns:discovery:2009:01</a:To></s:Header><s:Body><Probe xmlns=""http://docs.oasis-open.org/ws-dd/ns/discovery/2009/01""><d:Types xmlns:d=""http://docs.oasis-open.org/ws-dd/ns/discovery/2009/01"" xmlns:dp0=""http://tempuri.org/"">dp0:IDiscoveryService</d:Types><Duration xmlns=""http://schemas.microsoft.com/ws/2008/06/discovery"">PT5S</Duration></Probe></s:Body></s:Envelope>";
        string outgoingMessage = string.Format(outgoingMessageFormat, Guid.NewGuid().ToString());
        return outgoingMessage;
    }

    private async Task SendDiscoveryMessage(DatagramSocket socket)
    {
        using (var stream = await socket.GetOutputStreamAsync(new HostName(DEST_IP_WSDISCOVERY), DEST_PORT_WSDISCOVERY))
        {
            string message = BuildDiscoveryMessage();
            var data = Encoding.UTF8.GetBytes(message);
            using (var writer = new DataWriter(stream))
            {
                writer.WriteBytes(data);
                await writer.StoreAsync();
            }
        }
    }

    private void SocketOnMessageReceived(DatagramSocket sender, DatagramSocketMessageReceivedEventArgs args)
    {
        var dr = args.GetDataReader();
        string message = dr.ReadString(dr.UnconsumedBufferLength);

        _wsresponses.Add(new WSDiscoveryResponse(message, args.RemoteAddress, args.RemotePort));
    }
}

关于c# - UWP 应用中的 WCF 发现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37285149/

相关文章:

c# - Angular JS 应用程序因多发布请求而失败

.net - 如何配置 WCF Web 角色的消息大小(当前获取 HTTP 错误代码 500)

unity-game-engine - Windows.Devices.Bluetooth.dll

azure - 如何在 UWP 中自动同​​步本地(桌面)和 Web 数据库

c# - 尝试将文件从 UWP 应用程序上传到 Flask restful web api,失败

c# - FxCop 和 GAC 疯狂

c# - asp.net 角色管理器错误

c# - 按 len() 排序,但在 C# 的 linq 中

c# - 可以从主应用程序启动的带有 WinForms 的 DLL

c# - WCF 服务上的 XmlSerializer 反序列化时间波动