【问题标题】:How to get all devices in Network within Unity?如何在 Unity 中获取网络中的所有设备?
【发布时间】:2021-05-21 23:26:37
【问题描述】:

现在大约 8 小时以来,我一直在尝试找到一种方法,以便我可以接收与我在同一网络中的所有设备。我已经找到了一些方法来做到这一点,但所有这些方法都归结为 ping 网络中的所有 IP。如果 Unity 允许多线程,那将不是什么大问题。由于它不/基本上只允许 IEnumerator 我有一个问题,我必须一个接一个地执行每个 ping,这需要很多时间,你甚至不能使用 GUI。

我当前的代码如下所示:

public class AddressFinder {

    private List<Ping> pingers = new List<Ping>();
    private List<IPAddress> addresses = new List<IPAddress>();

    private int timeOut = 250;
    private int ttl = 5;
    private int instances;
    private MonoBehaviour m;

    public void Scan(MonoBehaviour mono, IPSegment ips, Action<List<IPAddress>> callback) {
        this.m = mono;
        m.StartCoroutine(ScanAsync(ips, callback)); // New Coroutine so the UI should not freeze
    }

    private IEnumerator ScanAsync(IPSegment ips, Action<List<IPAddress>> callback) {
        PingOptions po = new PingOptions(ttl, true);
        byte[] data = new System.Text.ASCIIEncoding().GetBytes("abababababababababababababababab");
        instances = 0;
        foreach(uint host in ips.Hosts()) {  // Itterate through all IPs in that network
            m.StartCoroutine(Send(IPHelper.ToIpString(host) // IP as String, data, po));
        }
        WaitForSeconds wait = new WaitForSeconds(0.05f);
        while(instances > 0) {
            yield return wait;
        }
        callback(addresses);
    }

    private IEnumerator Send(string ip, byte[] data, PingOptions po) {
        instances++;
        Ping p = new Ping();
        PingReply rep = p.Send(ip, timeOut, data, po);
        p.Dispose();
        if(rep.Status == IPStatus.Success)
            addresses.Add(IPAddress.Parse(ip));
        instances--;
        yield return new WaitForSeconds(0);
    }
}

这个 wcode 确实可以工作,但需要 4 分钟来测试我网络中的所有 253 个 IP。在此期间 UI 也会冻结。

我也尝试过使用统一 Ping,它看起来非常不一致,而且效果也不太好,因为它还需要很长时间才能获得 254 个 ping。

有没有人知道问题出在哪里或有其他想法让所有设备进入网络?

【问题讨论】:

  • 我不知道c#中是否有好的方法,但是您可以创建一个c ++库并为统一创建一个包装器吗?我不确定这是否可行,但只是一个想法。统一内可能有更好的解决方案;)。
  • @nka_Zz 也在考虑库,但我无法想象 Unity 没有办法...特别是因为它可以在纯 c# 中轻松实现。问题只是由于某种原因统一不允许 Ping 的异步操作。
  • 这有帮助吗? reddit.com/r/Unity3D/comments/6oui3f/multithreadingIncendiaryGames 的回答看起来很有帮助
  • 我明天去看看我真的要睡觉了。但据我所知,它是关于多线程的。我的问题是,由于某种原因new Ping().SendAsync(... 确实冻结了团结;(
  • Unity 实际上有自己的Ping 实现,您可以在Coroutine 中使用

标签: c# unity3d networking


【解决方案1】:

我找到了一种使用线程的方法。我实际上认为不应该在 Unity 中使用线程,但似乎只是不使用主线程之外的 Unity 操作,这意味着其他人是允许的。无论如何,这是我的代码:

using Ping = System.Net.NetworkInformation.Ping;

public class AddressFinder {

    public List<string> addresses = new List<string>();
    private MonoBehaviour m;

    Thread myThread = null;
    public int instances = 0;

    public AddressFinder(MonoBehaviour mono) {
        m = mono;
    }

    public void Scan(List<IPSegment> iPSegments, Action<List<string>> addresses) {
        myThread = new Thread(() => ScanThreads(iPSegments, addresses));
        myThread.Start();
    }

    private void ScanThreads(List<IPSegment> iPSegments, Action<List<string>> callback) {
        Ping myPing;
        PingReply reply;
        instances = 0;

        foreach(IPSegment ips in iPSegments) {
            foreach(uint hosta in ips.Hosts()) {
                string ip = IPHelper.ToIpString(hosta);
                Task.Factory.StartNew(() => {
                    myPing = new Ping();
                    instances++;
                    reply = myPing.Send(ip, 250);

                    if(reply.Status == IPStatus.Success) {
                        addresses.Add(ip);
                    }
                    instances--;
                }, TaskCreationOptions.PreferFairness | TaskCreationOptions.LongRunning);
            }
        }
        int i = 0;
        while(instances > 0) {
            if(i > 100)
                break;
            i++;
            Thread.Sleep(10);
        }
        callback(addresses);
    }
}
public class LobbyManager : MonoBehaviour {

    public UnityEngine.Object[] Games;
    private List<string> localAddresses = new List<string>();
    private List<string> hostAddresses = new List<string>();
    private Ping p;
    AddressFinder af;

    public void Start() {
        List<IPSegment> iPSegments = GetInterfaces(true);
        af = new AddressFinder(this);
        af.Scan(
            iPSegments,
            (addresses) => {
                localAddresses = addresses;
                foreach(string address in localAddresses) {
                    Debug.Log(address.ToString());
                }
            }
        );
    }

    public void Update() {

    }

    public List<IPSegment> GetInterfaces(bool showVPN) {
        List<IPSegment> ipsList = new List<IPSegment>();
        foreach(NetworkInterface ni in NetworkInterface.GetAllNetworkInterfaces()) {
            if(ni.Name.Contains("VM") || ni.Name.Contains("Loopback"))
                continue;
            if(!showVPN && ni.Name.Contains("VPN"))
                continue;
            foreach(UnicastIPAddressInformation ip in ni.GetIPProperties().UnicastAddresses) {
                if(ip.Address.AddressFamily == AddressFamily.InterNetwork) {
                    IPSegment ips = new IPSegment(ip.Address.ToString(), ip.IPv4Mask.ToString());
                    ipsList.Add(ips);
                }
            }
        }
        return ipsList;
    }
}

IPSegment是一个根据子网掩码保存该段内所有IP的类。

此代码运行良好,但性能不佳,这意味着子网掩码不应高于 255.255.255.0,否则将需要年龄。

【讨论】:

  • 为什么不允许在 Unity 中使用线程?它是 c#,因此您可以使用 c# 提供的任何东西;)但是要小心将结果传递/分派回主线程,否则您以后可能会从 Unity API 中得到错误;)
  • @derHugo 是的,我们刚刚了解到 Unity 不是线程安全的,我们被告知不要在 Unity 中使用线程。据我所知,您不应该在线程内使用 MonoBehaviour 的操作,而是可以在主线程以外的线程中执行其他所有操作。不确定这是否 100% 正确。
  • @derHugo 因为你说你可以使用 C# 提供的所有东西。您只能使用 .NET Framework 而不能使用 .NET Core,我说得对吗?还是我搞混了?
  • 你可以在线程中做更多的事情;)基本上所有基本的东西也是 Unity API 的,例如矢量和四元数操作等。但是基本上所有会直接影响您的场景(更改材质、实例化、移动等)的东西都只能从 Unity 主线程中使用 -> 如果您想以某种方式在您的场景(否则为什么要收集这些信息?)你必须确保以某种方式只在主线程中进行这些调用,例如使用ConcurrentQueue&lt;Action&gt; 在某处的Update 中工作;)
  • 是的,当然你只能使用相应的 c# 版本提供的东西;)并且 Unity 使用的是 .Net Framework 4.x(其中 afaik x 当前实际上是 6.2,但对此不确定一)
猜你喜欢
  • 2015-02-11
  • 2016-10-23
  • 2016-02-24
  • 2019-11-25
  • 1970-01-01
  • 1970-01-01
  • 2015-02-17
  • 1970-01-01
  • 2012-11-04
相关资源
最近更新 更多