Adobe Air - 如何检测LAN服务器(侦听特定端口)

时间:2014-01-14 11:23:17

标签: actionscript-3 flash networking air udp

我想知道如何检测局域网服务器。

我制作了一个客户端/服务器应用程序,一切正常,但您必须手动输入服务器的IP地址。

目前我正在尝试在客户端/服务器上使用DatagramSocket。 服务器将发送包含其IP地址的数据包,以便客户端可以连接到该地址。数据包将其发送到本地广播IP(192.168.1.255)端口4444.

客户端将侦听端口4444.然后接收数据包。

如果我在同一台计算机上(这样我的代码没有问题),这是有效的,但是当我在另一台计算机上尝试连接并尝试连接到我的计算机时却没有。

我不熟悉网络,所以我希望有人可以向我解释如何正确地做到这一点。

此外,不支持255.255.255.255的AIR广播:Note: Sending data to a broadcast address is not supported. source

3 个答案:

答案 0 :(得分:1)

要发现局域网中的其他计算机,您的服务器必须发送UDP广播,AIR不支持。如果您的服务器必须在AIR中实现,您可以使用本机扩展(android / ios)或通过执行UDP广播的NativeProcess(桌面)调用系统进程。

以下是一些可能有用的链接:

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

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

答案 1 :(得分: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);
}

这是我想要实现此功能的网络工具类:

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

答案 2 :(得分:0)

虽然您可以在Windows系统上使用192.168.0.255,但您将在MacOS X上获得例外。您可以在MacOS X上使用D类IP广播... 224.0.0.1