Actionscript 3 AdobeAIR-如何检测LAN服务器(侦听特定端口)

Actionscript 3 AdobeAIR-如何检测LAN服务器(侦听特定端口),actionscript-3,flash,networking,air,udp,Actionscript 3,Flash,Networking,Air,Udp,我想知道如何检测局域网服务器 我制作了一个客户端/服务器应用程序,一切正常,但您必须手动输入服务器的IP地址 目前,我正在尝试在客户机/服务器上使用DatagramSocket。 服务器将发送包含其IP地址的数据包,以便客户端可以连接到该地址。数据包被发送到其本地广播IP(192.168.1.255)端口4444 客户端将侦听端口4444。然后接收数据包 如果我在同一台计算机上(因此我的代码没有问题),但当我在另一台计算机上尝试并尝试连接到我的计算机时,这种方法就不起作用了 我不太熟悉网络,所以

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

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

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

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

如果我在同一台计算机上(因此我的代码没有问题),但当我在另一台计算机上尝试并尝试连接到我的计算机时,这种方法就不起作用了

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


另外,不支持255.255.255.255上的空中广播:
注意:不支持向广播地址发送数据。

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

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


为了实现这一点,我创建了自己的解决方案(这不是完美的,但却是我能想到的唯一可行的方法)

在服务器端,我创建了一个新的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);
            }
        }
    }
下面是我的network 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;
    }
}
导入flash.net.interfacedAddress;
导入flash.net.NetworkInfo;
导入flash.net.NetworkInterface;
公共类NetworkUtil
{
私有静态var地址:InterfaceAddress;
{//静态构造函数
getAddress();//获取此主机的地址
}
公共静态函数getAddress():void
{
var interfaceVector:Vector.=NetworkInfo.NetworkInfo.findInterfaces();
对于每个(变量networkInt:interfaceVector中的NetworkInterface){
如果(networkInt.active&&networkInt.displayName.toLowerCase()!=“hamachi”){//忽略hamachi接口
对于每个(变量地址:networkInt.addresses中的InterfaceAddress){
如果(addresss.ipVersion==“IPv4”){
如果(地址!=“127.0.0.1”){
跟踪(networkInt.displayName);//输出用于调试的iPAddress
地址=地址;
}
}
}
}
}
}
公共静态函数getPrefixLength():int
{
返回地址。前缀长度;
}
公共静态函数getBroadcastIp():字符串
{
返回地址.广播;
}
公共静态函数getIpAddress():字符串
{
返回地址。地址;
}
公共静态函数getSubnetIp(currentIp:Array,subnetMask:Array):字符串
{           
for(变量i:int;i<4;i++){
currentIp[i]=(子网掩码[i]==255?currentIp[i]:0);
}
返回currentIp[0]+“+currentIp[1]+”+currentIp[2]+“+currentIp[3];
}
公共静态函数getAmountOfHosts(前缀长度:int):int
{
返回(256=8){
预桥长度-=8;
}否则{
子网=255-(255>>前缀长度);
预桥长度=0;
}
子网掩码[i]=子网;
}
返回子网掩码;
}
公共静态函数isValidIp(ip:String):布尔值{
ip=ip.replace(//\s/g,“”;//删除空格以进行检查
变量模式:RegExp=/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/;
if(模式测试(ip)){
变量八位字节:数组=ip.split(“.”);
if(parseInt(字符串(八位字节[0]))==0){
返回false;
}
if(parseInt(字符串(八位字节[3]))==0){
返回false;
}
返回true;
}
返回false;
}
}

虽然您可以在Windows系统上使用192.168.0.255,但在MacOS X上会出现异常。相反,您可以在MacOS X上使用D类IP广播。。。224.0.0.1

谢谢你让我知道没有其他来源是不可能的。我甚至不确定AIR是否能接收到广播。在我看来,第一个家伙似乎必须用phyton脚本接收广播,该脚本将广播转发到同一台机器上的单播端口,实际的AIR客户端在那里收听。我正在尝试实现这一点。。请原谅我的无知,但你能解释一下子网掩码是如何工作的吗?@user5839是的,当然。我已经实现了这个功能来检查您当前所在的网络类型。如果是A或B网络,发送的数据包数量将过高,结果是无法找到服务器。我已经添加了networkutils类作为我的答案。我用它来获取子网掩码。您可以这样使用它:
NetworkUtil.getSubnetMask(NetworkUtil.getPrefixLength())
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;
    }
}