Networking with iPhone

Hi everybody.

I have a simple question :

Can we use Networking on iPhone but over 3G/ EDGE/GSM ?

On my dedicated server i’ve launched the masterserver and the facilitator.

I have a masterserver installed on my dedicated server (physical), when i launch the server (game) on the iphone, i see that it is well registered on the Dedicated server, and when i launch a client (from my desktop) it seems it cannot connect to my iphone ?

if i do inverse (desktop is server and iphone is client) it’s quite the same.

At least when i run a server on my desktop and a client on my desktop, all is ok.

PS : my dedicated server is hosted in a real web hoster.

is it due to problem with NAT ?

you can play games on 3g but you will near granted not be nat punchthroughable on phone network so you have to offer dedicated unity nodes for them to play on or it won’t work.

aside of that, the 100ms to 2xxxms latency is not exactly stunning for any realistic usage outside of turn based in which case a tcp socket might be a better approach

Hi dreamora do you say i need to make an authoritative server with network.dedicatedserver= true ?

Meaning all my room (server) have to be hosted and running on The dedicated server ? And iPhone players are Only client ?

In that case this should works ok on iPhone ?
If that case i Will change my networking architecture.

Thanks for your time…

:smile:

the problem is not dedicated true.
But initialize server at all as nat punchthrough is required to pass through firewalls to the udp port.

The problem is that can also hit you if they are just pure clients, thats something you optimally test with a simple test project (modification of networking example for example).

Question is what kind of game you do and if you potentially can save quite some headache by using TCP socket (or for simplicity the tcp client class), assuming you have iphone pro (if you host servers you at least have Unity Pro :wink: )

Yes i have the sockets you can see my registered products on my signature :smile:.
So, i have already network.usenat to true when i register The server (does it needs to be false ?).
The game Will be for 2 players (later 4 or more if ok with bandwith) it is not a Turn by Turn but The flow of data Will be quite limited.

You said to use eventually tcp (or udp) but is there any doc for it ? Is it as easy as unity networking built in ?

Or do you have a script to test how to connect/register to The server ? Nat true or not ? Havepublic adress…?

Thanks again.

usenat is the problem: it will generally (there might be exceptions) not work on mobile networks as the phone providers have non-punchthroughable firewalls and further protections.

For testing, I would recommend to rework one of the cases in the Networking Example project. I think there used to be an iphone one, unsure if its still around but I know that the two of them worked with each other (headless client on homeserver + iphone on wifi in my case as it was LAN internal testing)

as for tcp: There is a massive amount of docs on MSDN, go-mono and all over the WWW.
Its a standard .NET feature, no unity functionality :slight_smile:

I Will Check this in the unity network example.

About .net socket i know them but i thought There were Some specifical unity component for exemple to transmit physic :slight_smile:

Anyway i will check The méthod to Check how to register The server in The network example like you suggests me.

Ps iPhone on wifi it is working ! What i search is over 3G…

Thanks again.

physics transmit is a bad idea anyway (unity has no networked physics … I think no engine I’ve got in touch so far has it unless its physics is simple enough and not physx/havoc class physics simulation) and that without the 100 to 2xxxms latency which makes even extrapolation totally useless on rigidbodies

Ps iPhone on wifi is ok : î search over 3G.
Physic was an example :slight_smile: perhaps bad LOL

But i’ll continue to investigate to use masterserver and facilitator with iPhone networked games. Over 3G it should be possible :roll: ?

on wifi you don’t have the problems, right.
cause in that case, its your router that decides if nat punchthrough is possible.

but with 3G, GSM, EDGE, its your phone service provider that does and the broad standard is to not allow nat punchthrough (and as consequence also no game hosting on udp)

Perhaps something interesting :

In U3 there is The proxyserver.exe ( that comes with The masterserver and facilitator) perhaps this is thé best way ??

But there is no doc currently about it. Perhaps once U3 Will be released ?

Would guess so

Also its a u3 thing so unless you want to work with iphone 3 and u3 on desktop it wouldn’t do anything :slight_smile:

Sorry i didn’t understand :frowning:

Meant: Yes documentation will potentially to likely come later, if at all ( old one didn’t really have any )

and if you want to use it you must work with unity 3 and unity iphone 3, it won’t work with unity 2.x and iphone 1.x

Yes i AM currently working with U3 b7. iPhone et desktop ( but it is all in one)

So proxyserver.exe should be the solution ? You think ?

Ok i’ve found this :

Will try later tomorrow and let you know if working !

Thanks a lot again. Dreamora :smile:

depending on what it does. If it does what I expect it to do then yes but in that case it also has to be able to handle quite some traffic (potentially all traffic). Unsure on that.
Didn’t mess too much with that nor with the new policy server and domain policies to which webplayers are bound in u3

but you can just test it when you are on 3G only + having a dedicated server running at home.

I might be lazy but for such a type of game I would likely start with using Photon or SmartFox before going with unity networking or sockets, but thats just me :wink:

i’ve tested the script this morning but registering the server seems failed. :frowning:

Were you talking about that code ? :

DontDestroyOnLoad(this);

var gameName = "You must change this";
var serverPort = 25002;

private var timeoutHostList = 0.0;
private var lastHostListRequest = -1000.0;
private var hostListRefreshTimeout = 10.0;

private var natCapable : ConnectionTesterStatus = ConnectionTesterStatus.Undetermined;
private var filterNATHosts = false;
private var probingPublicIP = false;
private var doneTesting = false;
private var timer : float = 0.0;

private var windowRect = Rect (Screen.width-300,0,300,100);
private var hideTest = false;
private var testMessage = "Undetermined NAT capabilities";

// Enable this if not running a client on the server machine
//MasterServer.dedicatedServer = true;

function OnFailedToConnectToMasterServer(info: NetworkConnectionError)
{
	Debug.Log(info);
}

function OnFailedToConnect(info: NetworkConnectionError)
{
	Debug.Log(info);
}

function OnGUI ()
{
	windowRect = GUILayout.Window (0, windowRect, MakeWindow, "Server Controls");
}

function Awake ()
{
	// Start connection test
	natCapable = Network.TestConnection();
	
	// What kind of IP does this machine have? TestConnection also indicates this in the
	// test results
	if (Network.HavePublicAddress())
		Debug.Log("This machine has a public IP address");
	else
		Debug.Log("This machine has a private IP address");
}

function Update() {
	// If test is undetermined, keep running
	if (!doneTesting) {
		TestConnection();
	}
}

function TestConnection() {
	// Start/Poll the connection test, report the results in a label and react to the results accordingly
	natCapable = Network.TestConnection();
	switch (natCapable) {
		case ConnectionTesterStatus.Error: 
			testMessage = "Problem determining NAT capabilities";
			doneTesting = true;
			break;
			
		case ConnectionTesterStatus.Undetermined: 
			testMessage = "Undetermined NAT capabilities";
			doneTesting = false;
			break;
			
		case ConnectionTesterStatus.PrivateIPNoNATPunchthrough: 
			testMessage = "Cannot do NAT punchthrough, filtering NAT enabled hosts for client connections, local LAN games only.";
			filterNATHosts = true;
			Network.useNat = true;
			doneTesting = true;
			break;
			
		case ConnectionTesterStatus.PrivateIPHasNATPunchThrough:
			if (probingPublicIP)
				testMessage = "Non-connectable public IP address (port "+ serverPort +" blocked), NAT punchthrough can circumvent the firewall.";
			else
				testMessage = "NAT punchthrough capable. Enabling NAT punchthrough functionality.";
			// NAT functionality is enabled in case a server is started,
			// clients should enable this based on if the host requires it
			Network.useNat = true;
			doneTesting = true;
			break;
			
		case ConnectionTesterStatus.PublicIPIsConnectable:
			testMessage = "Directly connectable public IP address.";
			Network.useNat = false;
			doneTesting = true;
			break;
			
		// This case is a bit special as we now need to check if we can 
		// cicrumvent the blocking by using NAT punchthrough
		case ConnectionTesterStatus.PublicIPPortBlocked:
			testMessage = "Non-connectble public IP address (port " + serverPort +" blocked), running a server is impossible.";
			Network.useNat = false;
			// If no NAT punchthrough test has been performed on this public IP, force a test
			if (!probingPublicIP)
			{
				Debug.Log("Testing if firewall can be circumnvented");
				natCapable = Network.TestConnectionNAT();
				probingPublicIP = true;
				timer = Time.time + 10;
			}
			// NAT punchthrough test was performed but we still get blocked
			else if (Time.time > timer)
			{
				probingPublicIP = false; 		// reset
				Network.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;
		default: 
			testMessage = "Error in test routine, got " + natCapable;
	}
	//Debug.Log(natCapable + " " + probingPublicIP + " " + doneTesting);
}

function MakeWindow (id : int) {
	
	hideTest = GUILayout.Toggle(hideTest, "Hide test info");
	
	if (!hideTest) {
		GUILayout.Label(testMessage);
		if (GUILayout.Button ("Retest connection"))
		{
			Debug.Log("Redoing connection test");
			probingPublicIP = false;
			doneTesting = false;
			natCapable = Network.TestConnection(true);
		}
	}
	
	if (Network.peerType == NetworkPeerType.Disconnected)
	{
		GUILayout.BeginHorizontal();
		GUILayout.Space(10);
		// Start a new server
		if (GUILayout.Button ("Start Server"))
		{
			Network.InitializeServer(32, serverPort);
			MasterServer.RegisterHost(gameName, "stuff", "l33t game for all");
		}

		// Refresh hosts
		if (GUILayout.Button ("Refresh available Servers") || Time.realtimeSinceStartup > lastHostListRequest + hostListRefreshTimeout)
		{
			MasterServer.RequestHostList (gameName);
			lastHostListRequest = Time.realtimeSinceStartup;
		}
		
		GUILayout.FlexibleSpace();
		
		GUILayout.EndHorizontal();

		GUILayout.Space(5);

		var data : HostData[] = MasterServer.PollHostList();
		for (var element in data)
		{
			GUILayout.BeginHorizontal();

			// Do not display NAT enabled games if we cannot do NAT punchthrough
			if ( !(filterNATHosts  element.useNat) )
			{
				var name = element.gameName + " " + element.connectedPlayers + " / " + element.playerLimit;
				GUILayout.Label(name);	
				GUILayout.Space(5);
				var hostInfo;
				hostInfo = "[";
				// Here we display all IP addresses, there can be multiple in cases where
				// internal LAN connections are being attempted. In the GUI we could just display
				// the first one in order not confuse the end user, but internally Unity will
				// do a connection check on all IP addresses in the element.ip list, and connect to the
				// first valid one.
				for (var host in element.ip)
				{
					hostInfo = hostInfo + host + ":" + element.port + " ";
				}
				hostInfo = hostInfo + "]";
				//GUILayout.Label("[" + element.ip + ":" + element.port + "]");	
				GUILayout.Label(hostInfo);	
				GUILayout.Space(5);
				GUILayout.Label(element.comment);
				GUILayout.Space(5);
				GUILayout.FlexibleSpace();
				if (GUILayout.Button("Connect"))
				{
					// Enable NAT functionality based on what the hosts if configured to do
					Network.useNat = element.useNat;
					if (Network.useNat)
						print("Using Nat punchthrough to connect");
					else
						print("Connecting directly to host");
					Network.Connect(element.ip, element.port);			
				}
			}
			GUILayout.EndHorizontal();	
		}
	}
	else
	{
		if (GUILayout.Button ("Disconnect"))
		{
			Network.Disconnect();
			MasterServer.UnregisterHost();
		}
		GUILayout.FlexibleSpace();
	}
	GUI.DragWindow (Rect (0,0,1000,1000));
}