【问题标题】:How to check internet availability during single frame?如何在单帧期间检查互联网可用性?
【发布时间】:2018-01-22 16:06:28
【问题描述】:

在 Unity3D 中,有什么方法可以即时检查网络可用性? “立即”是指在单个帧期间,因为低于此检查的代码行需要根据网络可用性工作。

这一切都发生在Start() 期间。我知道我可以 ping 一个网页,并根据下载网页期间发生的任何错误获取网络可用性。但是,这样的操作需要几秒钟,而我需要立即知道结果,然后再转到脚本中的下一行代码。

【问题讨论】:

  • 否......
  • @Gusman 来吧,一定有办法...
  • 立即?没有。
  • 您需要执行 ping 以保证连接。可以移除电缆,本地 PC 仍然认为连接处于活动状态。当连接关闭时,客户端之间会发送一条消息并发生确认。简单地关闭路由器不会发送关闭消息。确保保持连接的唯一另一种方法是使用 keep-alive,它会定期发送零字节的消息来验证连接是否仍在工作。然后您可以检查连接是否立即工作。

标签: c# unity3d networking download


【解决方案1】:

假设您的游戏以 30fps 或更高的合理帧速率运行,那么您可以提出的任何解决方案(甚至 ping 您的服务器主机)将仅在往返延迟小于 1 的情况下有效/30 秒或更短(大约 30 毫秒)

因此,在帧之间处理这个是不现实的(可能在本地网络上除外)

相反,我建议研究线程化基于网络的代码以将其与帧分离

【讨论】:

    【解决方案2】:

    不要这样做。 只要您不提供更多关于您的计划的信息,就无法给您正确的答案。 这对双方都不满意。

    但是你实际上可以做什么:

    打开与 google.com 服务器等网络可用设备的 TCP 连接。 一旦网络状态发生变化(已连接、已断开......),就会触发一个简单的 c# 事件或设置一个变量,如 isOnline = true;。 这可以是一种方式。但它是一个坏的。

    【讨论】:

    • 男人,你是天才。谢谢。
    【解决方案3】:

    这一切都发生在Start()

    是的,这是可能的,如果是这种情况,可以在一帧内完成。如果在Update 函数中的每一帧都执行此操作,我会非常气馁,但事实并非如此。如果这是在应用程序的开头完成的,那很好。如果在游戏运行时这样做,将会影响性能。

    但是这样的操作需要几秒钟

    这样设计是为了避免阻塞主线程。

    网络操作应在Threadasync 方法中完成,以避免阻塞主线程。这就是大多数 Unity 网络 API(例如 WWWUnityWebRequest)的工作方式。他们在后台使用Thread,然后通过在帧上让出/等待协程函数中的协程函数直到网络请求完成,为您提供协程来管理该线程。

    要在一帧中完成此操作,只需使用 HttpWebRequest 并提供一个服务器 url 来检查。大多数示例使用google.com,因为它始终在线,但确保提供“User-Agent”,这样移动设备上的连接就不会被拒绝。最后,如果HttpStatusCode不是200或者有异常就说明有问题,否则就认为是连通的。

    bool isOnline()
    {
        bool success = true;
        try
        {
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://google.com");
            request.Method = "GET";
    
            //Make sure Google don't reject you when called on mobile device (Android)
            request.changeSysTemHeader("User-Agent", "Mozilla / 5.0(Windows NT 10.0; WOW64) AppleWebKit / 537.36(KHTML, like Gecko) Chrome / 55.0.2883.87 Safari / 537.36");
    
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
    
            if (response == null)
            {
                success = false;
            }
    
            if (response != null && response.StatusCode != HttpStatusCode.OK)
            {
                success = false;
            }
        }
        catch (Exception)
        {
            success = false;
        }
    
        return success;
    }
    

    用于更改 User-Agent 的自定义 changeSysTemHeader 函数的类:

    public static class ExtensionMethods
    {
        public static void changeSysTemHeader(this HttpWebRequest request, string key, string value)
        {
            WebHeaderCollection wHeader = new WebHeaderCollection();
            wHeader[key] = value;
    
            FieldInfo fildInfo = request.GetType().GetField("webHeaders",
                                                    System.Reflection.BindingFlags.NonPublic
                                                       | System.Reflection.BindingFlags.Instance
                                                       | System.Reflection.BindingFlags.GetField);
    
            fildInfo.SetValue(request, wHeader);
        }
    }
    

    Start 函数的简单用法在 one 框架中完成:

    void Start()
    {
        Debug.Log(isOnline());
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-01-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-09
      • 2014-10-13
      相关资源
      最近更新 更多