为了实现这一点,我创建了自己的解决方案(这并不完美,但我能想到的唯一工作方式)。
在服务器端,我创建了一个新的 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;
}
}