ネットワーク接続のテストを行います
マシンがパブリック ID を持っているか、あるいはプライベートアドレスしか持っていないかによって、二種類の異なるテストが行われます。
パブリック IP アドレスのテストは、主に、サーバーを実行している場合に使用されます。パブリックアドレスを持ったクライアントにはテストは必要ないからです。
パブリック IP テストを成功させるには、サーバーインスタンスを開始する必要があります。
テストサーバーが ローカルサーバーの IP とポートに接続を試み、接続可能な場合はサーバーに表示されます。
接続可能でない場合は、ファイアーウォールがサーバーポートをブロックしている場合がほとんどです。
テストサーバーの接続先として、サーバーインスタンスがひとつ実行されている必要があります。
もう一方のテストは NAT パンチスルーの機能を確認するものです。このテストはサーバーにもクライアントにも有効で、事前設定が必要ありません。
NAT テストの結果には、__Full Cone_、 Address Restricted Cone、 Port restricted、 Symmetric の 4 種類があります。
(詳しくは ConnectionTesterStatus をご参照ください。)
最初の 2 つのタイプは、NAT パンチスルーにフル対応しており、すべてのタイプに接続可能です。Port restricted タイプは、 Symmetric タイプへの接続(および同タイプからの接続受け入れ)ができません。
Symmetric タイプは、他の Symmetric タイプへの接続も、Port restricted タイプへの接続もできません。
NAT のパンチスルーを介入させる IP アドレス
この関数は非同期であり、有効な結果をすぐに返すとは限りません。テストの完了に、ある程度の時間(1~2秒)を必要とするためです。
テスト完了後、関数が再度呼び出されたときに初めて結果が返されます。
完全なネットワークテストが再度行われることはありません。このため、関数を頻繁にポーリングしても安全です。
ネットワーク接続を変更した場合などで再度テストが必要になった場合は、パラメーター forceTest
を True で返す必要があります。
この関数は ConnectionTesterStatus enum を返します。
var testStatus = "Testing network connection capabilities."; var testMessage = "Test in progress"; var shouldEnableNatMessage : String = ""; var doneTesting = false; var probingPublicIP = false; var serverPort = 9999; var connectionTestResult = ConnectionTesterStatus.Undetermined; // Indicates if the useNat parameter be enabled when starting a server var useNat = false; function OnGUI() { GUILayout.Label("Current Status: " + testStatus); GUILayout.Label("Test result : " + testMessage); GUILayout.Label(shouldEnableNatMessage); if (!doneTesting) TestConnection(); } function 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; } 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"; } }]></code> </example> <description>If you know both server and client NAT types you could use the following function to determine if the client can connect to the server or not.</description> <example> <code lang="js"><![CDATA[ function CanConnectTo(type1: ConnectionTesterStatus, type2: ConnectionTesterStatus) : boolean { if (type1 == ConnectionTesterStatus.LimitedNATPunchthroughPortRestricted && type2 == ConnectionTesterStatus.LimitedNATPunchthroughSymmetric) return false; else if (type1 == ConnectionTesterStatus.LimitedNATPunchthroughSymmetric && type2 == ConnectionTesterStatus.LimitedNATPunchthroughPortRestricted) return false; else if (type1 == ConnectionTesterStatus.LimitedNATPunchthroughSymmetric && type2 == ConnectionTesterStatus.LimitedNATPunchthroughSymmetric) return false; return true; }
using UnityEngine; using System.Collection;
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;
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; } 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"; } } }