2014-01-14 2 views
0

Интересно, как я могу обнаружить LAN-серверы.Adobe Air - Как обнаружить локальные серверы (прослушивание определенного порта)

Я сделал приложение клиент/сервер, и все это работает нормально, но вам нужно вручную ввести IP-адрес сервера.

В настоящее время я пытаюсь использовать DatagramSocket на клиенте/сервере. Сервер отправит пакет, содержащий его IP-адрес, чтобы клиент мог подключиться к этому адресу. Пакет отправляет его на свой локальный широковещательный IP-адрес (192.168.1.255) порт 4444.

Клиент будет слушать порт 4444. Затем получите пакет.

Это работает, если я нахожусь на одном компьютере (так что ничего плохого в моем коде), но не тогда, когда я пробую его на другом компьютере и пытаюсь подключиться к своему компьютеру.

Я не знаком с сетью, поэтому я надеялся, что кто-то сможет объяснить мне, как это сделать должным образом.

Кроме того, в радиовещании AIR на 255.255.255.255 не поддерживается: Note: Sending data to a broadcast address is not supported.source

ответ

1

Для достижения этой цели я создал свое собственное решение (которое не является совершенным, но только рабочим как я мог думать).

На стороне сервера я создаю новый DatagramSocket, который будет отправлять сообщение каждому адресу Ip в определенном диапазоне.

import flash.utils.setInterval; 
import flash.utils.clearInterval; 
.... 

    private const subnetMask:Array = NetworkUtil.getSubnetMask(NetworkUtil.getPrefixLength()); 
    private const ip:Array = NetworkUtil.getIpAddress().split("."); 
    private const ipBroadcastSocket:DatagramSocket = new DatagramSocket(); 
    private static var _broadcastIp:Boolean; 
    private static var intervalId:int; 
    .... 
    { 
    .... 
     intervalId = setInterval(broadcastIP, 2000, NetworkUtil.getIpAddress());//broadcast the servers Ip-Address every 2 seconds 
    } 

    private function broadcastIP(message:String):void 
    { 
     if(_broadcastIp){ 
      try 
      { 
       if(subnetMask[1] != 255 || subnetMask[2] != 255){ 
        trace("!!! WARNING: NOT A 'C' CLASS NETWORK !!! (Will not broadcast IP.)"); 
        clearInterval(intervalId); 
       } 
       else 
       { 
        var data:ByteArray = new ByteArray(); 
        data.writeUTFBytes(message); 

        for(var i4:int = subnetMask[3]; i4 <= 255; i4++){ 
         var tempIp:String = ip[0] + "." + ip[1] + "." + ip[2] + "." + (subnetMask[3] == 255 ? ip[3] : i4); 
         if(tempIp != NetworkUtil.getBroadcastIp() && tempIp != NetworkUtil.getSubnetIp(ip, subnetMask)){ 
          serverDatagramSocket.send(data, 0, 0, tempIp, port); 
         } 
        } 
       } 
      } 
      catch (error:Error) 
      { 
       trace(error.message); 
      } 
     } 
    } 

Затем на стороне клиента добавьте еще один DatagramSocket. Затем привяжите его к тому же порту, который используется сервером, и установите его в режим приема.

private var ipBroadcastSocket:DatagramSocket = new DatagramSocket(); 
ipBroadcastSocket.bind(4444); 
ipBroadcastSocket.addEventListener(DatagramSocketDataEvent.DATA, dataReceived); 
ipBroadcastSocket.receive(); 

private function dataReceived(e:DatagramSocketDataEvent):void 
{ 
    var data:String = e.data.readUTFBytes(e.data.bytesAvailable); 
    trace("Server found with IP: "+ data); 
} 

Вот моя сеть Utils класс для тех, кто хочет осуществить это:

import flash.net.InterfaceAddress; 
import flash.net.NetworkInfo; 
import flash.net.NetworkInterface; 

public class NetworkUtil 
{ 
    private static var address:InterfaceAddress; 

    {//static constructor 
     getAddress(); //Get the adress of this host 
    } 

    public static function getAddress():void 
    { 
     var interfaceVector:Vector.<NetworkInterface> = NetworkInfo.networkInfo.findInterfaces(); 
     for each (var networkInt:NetworkInterface in interfaceVector) { 
      if (networkInt.active && networkInt.displayName.toLowerCase() != "hamachi") { //Ignore the hamachi interface 
       for each (var addresss:InterfaceAddress in networkInt.addresses) { 
        if (addresss.ipVersion == "IPv4") { 
         if(addresss.address != "127.0.0.1"){ 
          trace(networkInt.displayName); //Output ipAdress for debugging 
          address = addresss; 
         } 
        } 
       } 
      } 
     } 
    } 

    public static function getPrefixLength():int 
    { 
     return address.prefixLength; 
    } 

    public static function getBroadcastIp():String 
    { 
     return address.broadcast; 
    } 

    public static function getIpAddress():String 
    { 
     return address.address; 
    } 

    public static function getSubnetIp(currentIp:Array, subnetMask:Array):String 
    {   
     for(var i:int; i < 4; i++){ 
      currentIp[i] = (subnetMask[i] == 255 ? currentIp[i] : 0); 
     } 

     return currentIp[0] + "." + currentIp[1] + "." + currentIp[2] + "." + currentIp[3]; 
    } 

    public static function getAmountOfHosts(prefixLength:int):int 
    { 
     return (256 << (24-prefixLength)) -2; 
    } 

    public static function getSubnetMask(prefixLength:int):Array 
    { 
     var subnetMask:Array = []; 

     for(var i:int = 0; i < 4; i++){ 
      var subnet:uint = 255; 
      if(prefixLength >= 8){ 
       prefixLength-=8; 
      }else{ 
       subnet = 255 - (255 >> prefixLength); 
       prefixLength=0; 
      } 

      subnetMask[i] = subnet; 
     } 
     return subnetMask; 
    } 

    public static function isValidIp(ip:String):Boolean { 
     ip = ip.replace(/\s/g, ""); //remove spaces for checking 
     var pattern:RegExp = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/; 

     if(pattern.test(ip)){ 
      var octets:Array = ip.split("."); 
      if (parseInt(String(octets[0])) == 0) { 
       return false; 
      } 
      if (parseInt(String(octets[3])) == 0) { 
       return false; 
      } 
      return true; 
     } 
     return false; 
    } 
} 
+0

Я пытаюсь реализовать это. Простите мое невежество, но не могли бы вы объяснить, как работает subnetMask? – user5839

+1

@ user5839 \t Да, конечно. Я реализовал это, чтобы проверить тип сети, в которой вы сейчас находитесь.Если его сеть A или B, количество отправляемых пакетов будет слишком высоким, и в результате он не сможет найти сервер. Я добавил класс network utils своим ответом. Я использую это, чтобы получить маску подсети. Вы используете его следующим образом: 'NetworkUtil.getSubnetMask (NetworkUtil.getPrefixLength());' – Duckdoom5

1

Чтобы обнаружить другие компьютеры в вашей локальной сети на сервер должен послать широковещательные UDP, который AIR не поддерживает. Если ваш сервер должен быть реализован в AIR, вы можете использовать собственное расширение (android/ios) или вызвать системный процесс через NativeProcess (рабочий стол), который выполняет широковещательную рассылку UDP.

Вот некоторые ссылки, которые могут быть полезны:

http://lucamezzalira.com/2011/07/29/multicast-udp-socket-in-adobe-air-with-python/

https://github.com/wouterverweirder/AIR-Mobile-UDP-Extension

+0

Спасибо, что сообщили, что это невозможно без других источников. – Duckdoom5

+0

Я даже не уверен, может ли ВОЗ получать трансляцию. Мне кажется, что парень из первого должен был получить трансляцию с помощью phyton-скрипта, который перенаправил его в одноадресный порт на том же компьютере, где слушал настоящий клиент AIR. –

0

В то время как вы можете использовать 192.168.0.255 на системах Windows вы получите исключение на MacOS X. Вместо этого, может использовать IP-вещание класса D на MacOS X ... 224.0.0.1

Смежные вопросы