尝试在Unity中使用Ping时出错 - C#

时间:2018-04-06 14:09:47

标签: c# unity3d ping

我正在尝试使用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);

    }

}

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

2 个答案:

答案 0 :(得分:0)

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

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

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

        }

    }

答案 1 :(得分:0)

以下是关于如何在主线程上/下执行此操作的一般概念:

(警告:未经测试)

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);
    }
}

要从后台线程调用主线程,请查看主线程调度程序,例如:

https://en.wikipedia.org/wiki/ISO_4217