如何在单帧期间检查互联网可用性?

时间:2018-01-22 16:06:28

标签: c# unity3d networking download

在Unity3D中,有没有办法立即检查网络可用性?立即"立即",我的意思是在一个帧中,因为此检查下方的代码行需要根据网络可用性工作。

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

3 个答案:

答案 0 :(得分:5)

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

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

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

答案 1 :(得分:4)

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

您实际可以做的事情:

打开与google.com服务器等网络可用设备的TCP连接。 更改网络状态(连接,断开连接,...)后,触发简单的c#事件或设置类似isOnline = true;的变量。 这可以成为一种方式。但这是一个糟糕的。

答案 2 :(得分:2)

  

这一切都发生在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功能的简单使用:

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