【问题标题】:Error when trying to use Ping in Unity - C#尝试在 Unity 中使用 Ping 时出错 - C#
【发布时间】:2018-04-07 00:31:03
【问题描述】:

我正在尝试使用 C# Ping ping 我的一台服务器以查看它是否可用,但我收到一个奇怪的错误,我不确定是什么原因造成的

在第一次执行代码时,它会返回一个错误但说明操作已成功完成

System.Net.Sockets.SocketException (0x80004005): The operation completed successfully.\r\n\r\n at System.Net.Sockets.Socket..ctor (System.Net.Sockets.AddressFamily addressFamily, System.Net.Sockets.SocketType socketType, System.Net.Sockets.ProtocolType protocolType) [0x00069]

每次代码在第一次之后执行,都会返回不同的错误。

"An attempt was made to access a socket in a way forbidden by its access permissions."

System.Net.Sockets.SocketException (0x80004005)

我用来 ping 的代码如下,它几乎是直接从 MSDN 中提取的。 https://msdn.microsoft.com/en-us/library/system.net.networkinformation.pingreply(v=vs.110).aspx

  public static bool pingHost(string nameOrAddress)
    {
        bool pingable = false;

        if (nameOrAddress == "127.0.0.1")
        {
            return true; 
        }

        try
        {
            System.Net.NetworkInformation.Ping pingSender = new System.Net.NetworkInformation.Ping();
            PingOptions options = new PingOptions();

            // Use the default Ttl value which is 128,
            // but change the fragmentation behavior.
            options.DontFragment = true;

            // Create a buffer of 32 bytes of data to be transmitted.
            string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
            byte[] buffer = Encoding.ASCII.GetBytes(data);
            int timeout = 3;//3 seconds?
            PingReply reply = pingSender.Send(nameOrAddress, timeout);
            if (reply.Status == IPStatus.Success)
            {
                pingable = true;
            } else
            {
                pingable = false;
            }
        }
        catch (PingException e)
        {
            Debug.Log("Error pinging: " + e.Message + " - " + e.StackTrace);
            // Discard PingExceptions and return false;
        }
        return pingable;
    }

我可以从我机器上的终端 ping 服务器,但不能通过代码。为什么我会收到此错误?


编辑

我已经在标准 C# 应用程序中测试了代码,它运行良好。这个问题一定和 Unity 有关。

Unity 有自己的 Ping 类,但不能从主线程外部调用。下面的代码试图利用这一点,但它总是返回 false 和 -1。

Ping 肯定应该在 3 秒内完成?我尝试将这个时间增加到 10 秒,但仍然返回 false。该地址绝对可以 ping 通,因为我可以从终端 ping 通它。

IEnumerator ping()
    {
        while (true)
        {
            UnityEngine.Ping pinger = new UnityEngine.Ping("ADDRESS");

            yield return new WaitForSeconds(3.0f);

            Debug.Log("Ping finished? " + pinger.isDone + " - " + pinger.time);

            yield return new WaitForSeconds(2.0f);
        }

    }

由于这不起作用,我的下一个问题是 Unity ping 实际上是如何工作的?我的服务器处于安全环境中,只有特定的开放端口。如果它正在执行除标准 ping 之外的意外操作,它可能无法执行。


编辑 2

 IEnumerator ping()
{
    while (true)
    {
        WaitForSeconds f = new WaitForSeconds(0.05f);
        Ping p = new Ping("ADDR");

        while (!p.isDone)
        {
            yield return f;
        }
        PingFinished(p);

    }

}

这段代码似乎运行良好,但只能在主线程中运行。我需要一个能够从单独的任务或线程启动的解决方案。

【问题讨论】:

  • 您的代码是在降低安全性的上下文中运行还是在沙箱中运行?
  • @RonBeyer 我不知道。我正在使用 Unity 游戏引擎,它在单独的线程上运行。这也在我的家用机器上以管理员权限运行。
  • 尝试将超时设置为3000 而不是3,值以毫秒为单位。
  • @RonBeyer 奇怪,我刚刚意识到代码第一次运行时会返回错误,但会显示System.Net.Sockets.SocketException (0x80004005): The operation completed successfully.。之后每次都会返回权限错误。超时增加也没有解决问题,但感谢您指出。

标签: c# unity3d ping


【解决方案1】:

这似乎有效,但仅限于主线程。

 IEnumerator ping()
    {
        while (true)
        {
            WaitForSeconds f = new WaitForSeconds(0.05f);
            Ping p = new Ping("ADDR");

            while (!p.isDone)
            {
                yield return f;
            }
            PingFinished(p);

        }

    }

【讨论】:

    【解决方案2】:

    以下是关于如何在主线程上/关闭主线程的总体思路:

    (注意:未经测试)

    using System.Threading;
    class Test : MonoBehaviour {
        Ping result;
        private object pingLock;
    
        void Start() {
            pingLock = new object();
            new Thread(ThingRunningOffMainThread).Start();
            StartCoroutine(DoPing());
        }
    
        IEnumerator DoPing()
        {
            WaitForSeconds f = new WaitForSeconds(0.05f);
            Ping p = new Ping("ADDR");
    
            while (!p.isDone)
            {
                yield return f;
            }
            Monitor.Enter(pingLock);
            result = p;
            Monitor.Pulse(pingLock);
            Monitor.Exit(pingLock);
        }
    
    
        void ThingRunningOffMainThread() {
            if (result == null) {
                Monitor.Enter(pingLock);
                while (result == null) {
                    Monitor.Wait(pingLock);
                }
                Monitor.Exit(pingLock);
            }
            PingFinished(pingLock);
        }
    }
    

    要从后台线程调用到主线程,请查看 Main Thread Dispatchers,例如:

    https://github.com/PimDeWitte/UnityMainThreadDispatcher/blob/master/UnityMainThreadDispatcher.cs

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-09-10
      • 2015-12-30
      • 2023-03-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-12-21
      • 1970-01-01
      相关资源
      最近更新 更多