2015-05-26 7 views
2

Я пытаюсь создать веб-сервис для клиентов в локальной сети. Для службы я могу настроить таргетинг на любую версию .NET Framework. Клиенты - мобильные устройства для Windows, и я бы хотел использовать универсальную платформу Windows (UWP) в качестве целевой структуры.Windows UWP Web Service Discovery по LAN

Услуга будет работать на нескольких компьютерах с различными сетевыми адресами. Моя цель заключается в том, что клиент может автоматически обнаружить службу, как только он подключится к этой локальной сети. Я хочу избежать ввода пользователем IP-адресов. Но все образцы, которые я могу найти, используют жестко закодированный URL службы. Поскольку у меня нет DNS-сервера, я должен ввести (или жестко-кодовый) адрес-ip-адрес в клиенты.

В настоящее время им управляет служба WCF с UDPDiscoveryEndpoint, которая выполняет именно то, что я хочу. Но, к сожалению, эта часть WCF (пространство имен System.ServiceModel.Discovery) недоступна в WinRT, а также не поддерживается на универсальной платформе Windows. Мне не нужно использовать WCF; любая альтернативная библиотека с функциональностью обнаружения сервисов была бы идеальной.

Итак, вот мой вопрос: есть ли способ сделать открытие службы в локальной сети в приложении WinRT/UWP? Я пробовал ASP.NET Web API и SignalR, но кажется, что эти службы/фреймворки, основанные на HTTP, вообще не поддерживают обнаружение.

Спасибо!

ответ

1

Мне удалось выполнить обнаружение веб-сервисов в UWP, используя сокет и широковещательные сообщения.

Plese, проверьте my answer для получения более подробной информации.

EDIT - Как было сказано @ naveen-vijay, я отправляю более полный aswer вместо ссылки на решение.

Каждый WS будет прослушивать определенный порт, ожидая какого-то широковещательного сообщения, ищущего 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 }); 
       } 
      } 
     } 
    } 
} 
+0

Хотя эта ссылка может ответить на вопрос, лучше включить здесь основные части ответа и предоставить ссылку для справки. Ответные ссылки могут стать недействительными, если связанная страница изменится. - [Из обзора] (/ review/low-quality-posts/12408887) –

+0

@ naveen-vijay, спасибо, что указали это для меня. Я только что отредактировал свой ответ. Извините, я новичок в предоставлении ответов.Скажите, пожалуйста, если я сделал это неправильно снова. –

0

В UWP, вы можете использовать PeerFinder класс, чтобы обнаружить другие экземпляры приложений в локальной сети.

Я знаю, что это не точно открытие сервисов, это просто одноранговое открытие, но этого должно быть достаточно для вашего сценария. Просто используйте один экземпляр приложения как ваш «сервис», который связывается с другими экземплярами.

Вы можете использовать это, чтобы найти коллег и создать сокет:

PeerFinder.DisplayName = "Doru " + Guid.NewGuid().ToString(); 

    PeerFinder.ConnectionRequested += PeerFinder_ConnectionRequested; 

    PeerFinder.Start(); 

    private async void PeerFinder_ConnectionRequested(object sender, ConnectionRequestedEventArgs args) 
    { 
     PeerInformation peer = args.PeerInformation; 

     StreamSocket socket = await PeerFinder.ConnectAsync(peer); 
    } 

Для более глубокого понимания того, как Peer Discovery работает, выписка this ссылка [минут 6:30].