测试此机器的网络连接。
根据机器具有公共 IP 地址还是仅有私有地址,可执行两种测试。
公共 IP 地址测试主要用于作为服务器运行的情形,因为具有公共地址的客户端无需测试。为了
成功进行公共 IP 测试,必须启动一个服务器实例。测试服务器会尝试连接到本地服务器的 IP 和端口,
以显示该服务器可接受连接。否则,服务器端口很有可能被防火墙阻止。
服务器实例需处于运行状态,以便测试服务器能够建立连接。
另一个测试是检查 NAT 穿透能力。该测试对服务器和客户端均有效,
而且无需事先设置就可以进行测试。NAT 测试会有 4 种结果(请参阅 ConnectionTesterStatus):__Full Cone_、Address Restricted Cone、Port restricted 及
Symmetric。
前两种提供完全 NAT 穿透支持,可连接到任何类型。端口限制类型无法连接到对称类型,也不能接收来自对称类型的连接。
对称类型是最糟糕的情况,无法连接到其他对称类型或端口限制类型。后两种被标记为
提供有限的 NAT 穿透支持。
此函数是异步函数,可能不会立即返回有效的结果,
因为测试需要一定时间才能完成(1-2 秒)。测试完成后,测试结果仅在下一次再次调用该函数时返回,
不会重复进行一次完整的网络测试。这使得能够安全地频繁轮询该函数。如果希望进行另一个测试,
如网络连接是否发生变化,传入的 forceTest
参数应为 true。
此函数返回一个 ConnectionTesterStatus 枚举。
using UnityEngine;
using System.Collections;
public class ExampleClass : MonoBehaviour
{
string testStatus = "Testing network connection capabilities.";
string testMessage = "Test in progress";
string shouldEnableNatMessage = "";
bool doneTesting = false;
bool probingPublicIP = false;
int serverPort = 9999;
bool useNat = false;
float timer = 0.0f;
ConnectionTesterStatus connectionTestResult = ConnectionTesterStatus.Undetermined;
void OnGUI()
{
GUILayout.Label("Current Status: " + testStatus);
GUILayout.Label("Test result : " + testMessage);
GUILayout.Label(shouldEnableNatMessage);
if (!doneTesting)
TestConnection();
}
void TestConnection()
{
// Start/Poll the connection test, report the results in a label and
// react to the results accordingly
connectionTestResult = Network.TestConnection();
switch (connectionTestResult)
{
case ConnectionTesterStatus.Error:
testMessage = "Problem determining NAT capabilities";
doneTesting = true;
break;
case ConnectionTesterStatus.Undetermined:
testMessage = "Undetermined NAT capabilities";
doneTesting = false;
break;
case ConnectionTesterStatus.PublicIPIsConnectable:
testMessage = "Directly connectable public IP address.";
useNat = false;
doneTesting = true;
break;
// This case is a bit special as we now need to check if we can
// circumvent the blocking by using NAT punchthrough
case ConnectionTesterStatus.PublicIPPortBlocked:
testMessage = "Non-connectable public IP address (port " +
serverPort + " blocked), running a server is impossible.";
useNat = false;
// If no NAT punchthrough test has been performed on this public
// IP, force a test
if (!probingPublicIP)
{
connectionTestResult = Network.TestConnectionNAT();
probingPublicIP = true;
testStatus = "Testing if blocked public IP can be circumvented";
timer = Time.time + 10;
}
// NAT punchthrough test was performed but we still get blocked
else if (Time.time > timer)
{
probingPublicIP = false; // reset
useNat = true;
doneTesting = true;
}
break;
case ConnectionTesterStatus.PublicIPNoServerStarted:
testMessage = "Public IP address but server not initialized, " +
"it must be started to check server accessibility. Restart " +
"connection test when ready.";
break;
case ConnectionTesterStatus.LimitedNATPunchthroughPortRestricted:
testMessage = "Limited NAT punchthrough capabilities. Cannot " +
"connect to all types of NAT servers. Running a server " +
"is ill advised as not everyone can connect.";
useNat = true;
doneTesting = true;
break;
case ConnectionTesterStatus.LimitedNATPunchthroughSymmetric:
testMessage = "Limited NAT punchthrough capabilities. Cannot " +
"connect to all types of NAT servers. Running a server " +
"is ill advised as not everyone can connect.";
useNat = true;
doneTesting = true;
break;
case ConnectionTesterStatus.NATpunchthroughAddressRestrictedCone:
case ConnectionTesterStatus.NATpunchthroughFullCone:
testMessage = "NAT punchthrough capable. Can connect to all " +
"servers and receive connections from all clients. Enabling " +
"NAT punchthrough functionality.";
useNat = true;
doneTesting = true;
break;
default:
testMessage = "Error in test routine, got " + connectionTestResult;
break;
}
if (doneTesting)
{
if (useNat)
shouldEnableNatMessage = "When starting a server the NAT " +
"punchthrough feature should be enabled (useNat parameter)";
else
shouldEnableNatMessage = "NAT punchthrough not needed";
testStatus = "Done testing";
}
}
}