Search Unity

So... Networking...

Discussion in 'Multiplayer' started by Nihil688, Nov 10, 2014.

  1. Nihil688

    Nihil688

    Joined:
    Mar 12, 2013
    Posts:
    503
    Hello, I am kinda new to the Networking concept. I have so far managed to use Unity's master server functionality and created a local network with RPCs being sent properly. I did this by creating one server on one computer and a client on a mobile and vice versa.

    When I try to connect from a different network I get nat punchthroughs errors and even though the client finds the server it can't connect.

    I tried changing the ip before the server is instantiated and couldnt ever get the server to commence.

    Is there anything that I am missing? All I want is one user to become server and the other a client so they can send messages between themselves.

    I started looking into Photon, uLink and Google Play Game Services but I am not sure what to use. I do lean towards the latter as it's free.

    Any tips? Best
     
  2. Nihil688

    Nihil688

    Joined:
    Mar 12, 2013
    Posts:
    503
  3. FuzzyQuills

    FuzzyQuills

    Joined:
    Jun 8, 2013
    Posts:
    2,871
    Well, I am presuming you're using Unity Networking for this, So first, a checklist:
    • How are you trying to connect? If it is through a custom Master Server, I can give a more detailed explanation on how to set one up correctly. If you're using Unity's default server, then everything, so long as you have a network connection to the internet, should work straight away. Note that your code has to point to the URL for your master server when using a custom one.
    • If however, you are using LAN, you will have to make a part of your script show the IP and port. In the part where the client connects, add fields for entering the IP and port, then your client can connect directly. Another way is UDP broadcast, but this is disabled in Unity free mobile, and is also an advanced subject, going by my knowledge.
    There is how connections work, in a nutshell. As for your problem...
    It appears either your script has nat punchthrough forced on, (This wont work in networks that don't need it) or, if you're using a custom master server, the facilitator didn't start. If trying to start the facilitator on your sserver machine results in this:
    Code (csharp):
    1. ERROR: Failed to start RakPeer!
    Just reboot your machine, and the error shouold go away.

    Another thing to point out: if it's a LAN connection, ALWAYS HAVE NAT SET TO FALSE! it won't work with it on, as there is no master server involved!

    I can give some code examples from my networking script if you need them, to explain some of the info above better. :)
     
    Last edited: Nov 13, 2014
  4. Nihil688

    Nihil688

    Joined:
    Mar 12, 2013
    Posts:
    503
    Unfortunately none of these answer my initial question which is basically how do I connect two devices in two different networks?

    From what I gather I need to create a master server in a server somewhere with a public IP and connect the two users there but is that final? Isn't there any way that one user can use his own IP to create that server and the other connects to him?

    If the above is difficult to achieve then which should I pick? Photon, uLink or Google Play Game Services
     
  5. FuzzyQuills

    FuzzyQuills

    Joined:
    Jun 8, 2013
    Posts:
    2,871
    You can on a LAN, but on the internet, it's more complex, and made easier with the master server.

    I will give a roundown on how IPs work over the internet, shall I? :)
    Basically, (You probably know this already) every router and internet connection in each person's home has a local network (LAN) and a router that connects to the outside world. (The internet) To do this, the router's job is to grab requests from the LAN computers, and send it out through a different IP. (Your public IP address)

    Consider this tree diagram:
    Code (csharp):
    1.  
    2.                Internet
    3.                      | (Public IP applies here)
    4.                 Router
    5.                      | (LAN IP applies here)
    6.           Client Computers
    7.  
    Here, our client may want to, say connect to google.com. (Classic example, I know! :D) What happens is that when the computer does this, it sends the request to the router over the network. Then the router translates the local IP to the public one your ISP assigned to it. (I find it's always assigned the same IP every time) this Public IP is used to then fetch the data from the server, then once received, pass it to the LAN computer asking for it.

    But what if you want to connect one device to another remotely? Well, you would think only one Local IP would do. Not so, as they, in your case exist on two different networks! To access such device, both of them need to be aware of their connected router's public IP. (Let's say one of them uses 203.189.3.232, and the other uses 122.150.181.242) to connect to one of them, the device that want's to connect need sto query this to get to the device.

    Here is where the weird stuff comes in: Once a device has made a request, sure, it can be received by the router however you like, but then there's the problem of which device to forward the request to!

    The fix: in any type of networking software, including games, the server being communicated to usually uses both an IP address (usually a local one, with a router providing the public one for remote access) and a port. The port is the key here, as the port is where the data is forwarded through. To tell the router which computer will take the request, you use port forwarding on the router, and the router takes care of the rest.

    Also, since a public IP can be prone to change, it is also recommended one uses a domain name and a DNS service to host the public IP. no-ip.com has a good free service. what you do is set up an A-type DNS record, and have it point to your public IP. that way, any device can grab the URL, query the public IP from the address table, and then use the newly acquired IP to connect to the remote server.

    For your case, it is as simple as either deploying a master server (Which is actually not all that simple for beginners) or using Unity's. either way, just use that to connect your two devices from separate networks.

    That is all for now.

    EDIT: I will also note that technically, in theory, one could run the unity master server executables themselves and use them to make their own server, but in practice, it is pretty unwieldy, and a much better idea is to hand such duties to a remote server on the internet.
     
  6. Nihil688

    Nihil688

    Joined:
    Mar 12, 2013
    Posts:
    503
    Basically I was referring to this, but I love how you explained everything in great detail, thank you.


    By deploying do you mean using the MasterServer.RegisterHost method or http://docs.unity3d.com/Manual/net-MasterServerBuild.html (in the latter I see a Raknet implementation, does that mean I need to install Raknet? )
     
  7. FuzzyQuills

    FuzzyQuills

    Joined:
    Jun 8, 2013
    Posts:
    2,871
    for the former, yes. RegisterHost takes care of setting up the IP addresses for other devices to see by looking up the generated HostData on that server.

    As for the latter, no, you don't actually need the RakNet library, as the source code comes with it built-in.

    By looking at your PM however, it appears you wish to integrate such functionality offered by the master server into the game itself to make it standalone. As far as I know, unless a third-party library has support for this, it isn't possible to do that with Unity's default networking system. Maybe we might get lucky with the new library in Unity 5... :D

    Also, such functionality is guaranteed to run down an android phone's battery in no time. This is because it has to not just play the game, but manage all the stuff the master server does too. (The master server alone on any computer eats up 250MB RAM minimum, and possibly takes up more on faster systems)

    Long story short, having a server out on the internet instead of built-in to your game means the phone only has to take care of the game multi-player, and can give other duties, like keeping the connection up, to the master server. That way, the battery has less of a burden, and overall, the game will run better with only game sync to take care of.

    EDIT: Will also point out that even without networking, I reckon my tablet (A modified pendoPad PP4MT-7) with one of my unity games alone would run down in less than 2 hours with solid gaming throughout.
     
  8. Nihil688

    Nihil688

    Joined:
    Mar 12, 2013
    Posts:
    503
    This is a fair point! After our conversation Im thinking of using the Google play services to setup the server as I did give the master server a try but to no avail which is rare of me but I think Google will treat us well
     
  9. FuzzyQuills

    FuzzyQuills

    Joined:
    Jun 8, 2013
    Posts:
    2,871
    What happened when you tried setting up the master server? I have definitely set one up successfully before, so I can help! :)

    And is it even possible to use Google Play multi-player servers? Of course, one could have developed a plugin... :D
     
  10. Nihil688

    Nihil688

    Joined:
    Mar 12, 2013
    Posts:
    503
    So I downloaded the master server plugin, built in release both VS projects and ran both .exe
    Made an account in no-ip and got an ip setup

    but
    - I couldn't make my PC a Master Server since again I got the same NAT problems as before
    - I do have a shared server so that means I can't ran console inputs to start a MasterServer in my server

    Now unless I am misunderstanding something in my above tried you can certainly help me with some step by step love :)
     
  11. FuzzyQuills

    FuzzyQuills

    Joined:
    Jun 8, 2013
    Posts:
    2,871
    Sure!

    By NAT issues, did you mean messages like "failed to connect to facilitator?" This means you are using Network.InitializeServer with NAT forced on.

    Instead of this:
    Code (csharp):
    1. Network.InitializeServer(<ip>, <port>, true);
    Use this:
    Code (csharp):
    1. Network.InitializeServer(<ip>, <port>, !Network.havePublicAddress());
    That way, if the NAT isn't needed, it will be turned off for you.

    As for other problems: Is your A-record set right? Here is how the settings should look (This is my domain page as I set it up):
    No-IPSetup.png
    In the IP address field, put the IP you get from wahtismyip.com into this field, make sure it's an A-record, and then click save.

    Also, if this is setup correctly, how are you getting the URL? I can help do this, as it isn't obvious what to do if you're a first-timer... :D But I got it working! :)

    What kind of shared server? if it's a Linux machine... Oh wait, you're using windows! (Derp... :D)
    So you're saying you don't have access to the command prompt? o_O Well, another way to do the command-line arguments is through a windows shortcut:
    Shortcut CMD.png
    Basically, where the path is, put your path in, then your parameters after it. Good alternative to CMD, don't you think? :)
    Also, see if ticking "Run as Admin" works if the above fails.

    EDIT: also for future reference: if you ever use linux to run a server (I do recommend this, as it is less likely to fail due to some weird software in the background... :D) using the Function keys (F2-F6 I think) gives you several console windows, of which you can use two terminals to start masterserver and facilitator at once. Just press one of them to switch to another console terminal, then input your commands! :)
     
    Last edited: Nov 14, 2014
  12. Nihil688

    Nihil688

    Joined:
    Mar 12, 2013
    Posts:
    503
    I get the NAT issues because one device uses network #1 and the other network #2. The error is: "Receiving NAT punchthough attempt from target xxxxxx failed"

    When I say shared server is one of those servers where you store websites not a dedicated one. And it's linux btw. I tried to setup my PC to be a server in the above example though which is a Windows PC.

    You can check the code I sent you in the IM to see exactly what I am doing but it's as simple as:

    Code (CSharp):
    1. //SERVER
    2. NetworkConnectionError error = Network.InitializeServer(10, port, !Network,HavePublicAddress());
    3.  
    4. void OnServerInitialized()
    5. {
    6.        MasterServer.RegisterHost("xxx", ""+ port);
    7. }
    8.  
    9.  
    10. //CLIENT
    11. MasterServer.RequestHostList("xxx");
    12. hostList = MasterServer.PollHostList();
    13. if(hostList.Length >0)
    14. {
    15.        Network.Connect(hostList[0]);
    16. }
    17.  
     
    Last edited: Nov 15, 2014
  13. FuzzyQuills

    FuzzyQuills

    Joined:
    Jun 8, 2013
    Posts:
    2,871
    In this line:
    Code (csharp):
    1. NetworkConnectionError error = Network.InitializeServer(10, port, false);
    Change it to this:
    Code (csharp):
    1. NetworkConnectionError error = Network.InitializeServer(10, port, !Network.HavePublicAddress());
    See what happens, I guarantee it should work. if not... then something on your master server end isn't working right. :)
     
  14. Nihil688

    Nihil688

    Joined:
    Mar 12, 2013
    Posts:
    503
    Apologies, I do have it as you have it and get the error: "Receiving NAT punchthough attempt from target xxxxxx failed"

    Also I haven't setup anything else, that's what I am missing, there is no MasterServer somewhere else, that's all the code I have because I was trying to use device #1 as a server and device #2 as a client without connecting to any web server.
     
  15. FuzzyQuills

    FuzzyQuills

    Joined:
    Jun 8, 2013
    Posts:
    2,871
    Hmmm... Can you give me a console screenshot, so I can read it? o_O
     
  16. Nihil688

    Nihil688

    Joined:
    Mar 12, 2013
    Posts:
    503
    It only says this "Receiving NAT punchthrough attempt from target 123456789 failed" as error on the client side.
    The code used is only the above, devices are on different networks

    Step 1: Create Server
    Step 2: Client connects to server ( it can see the server but it can't connect )
     
  17. FuzzyQuills

    FuzzyQuills

    Joined:
    Jun 8, 2013
    Posts:
    2,871
    Ok, are you grabbing the hostData from the master server to connect on your client? o_O

    I forgot to check that first... :D
     
  18. Nihil688

    Nihil688

    Joined:
    Mar 12, 2013
    Posts:
    503
    Err.. No, as I said, Im only doing what you see, no extra code or anything...

    Device #1:
    - init server
    - On server init, masterServer register game

    Device #2:
    - request host list
    - connect to host[0]
     
  19. FuzzyQuills

    FuzzyQuills

    Joined:
    Jun 8, 2013
    Posts:
    2,871
    Wait, did you say you connect to hostData[0]?

    That isn't how I did it. I used a for-loop in OnGUI to set up a list of buttons of which each generated button, when clicked, will connect to the hostData addresses.

    Just using Host[0] probably won't work, IMO. At this point, I may as well make my network module more modular, and give it to you. :)

    Actually, what is the web address of your MasterServer? I can give a shot at a connection when I get home if you like: Just tell me when servers are online, and I will attempt one. If my network code doesn't work, then something isn't right with your server setup.
     
  20. Nihil688

    Nihil688

    Joined:
    Mar 12, 2013
    Posts:
    503
    Probably because there isn't any :D What you see in the above code is ALL the code Im using. I havent setup any server as I dont know how :)
     
  21. FuzzyQuills

    FuzzyQuills

    Joined:
    Jun 8, 2013
    Posts:
    2,871
    Ok, it appears you're calling RegisterHost in OnServerInitialized()

    What I do is this:
    Code (csharp):
    1.  
    2. function StartServer () {
    3. var ip : IPHostEntry = Dns.GetHostEntry (<URL>);
    4.         var ipA : IPAddress[] = ip.AddressList;
    5.         print(ipA[0].ToString());
    6.         if (ipA.Length > 0){
    7.             Network.natFacilitatorIP = ipA[0].ToString();
    8.             Network.natFacilitatorPort = 42100;
    9.         }
    10.         ip = Dns.GetHostEntry (<URL>);
    11.         ipA = ip.AddressList;
    12.         print(ipA[0].ToString());
    13.         if (ipA.Length > 0)
    14.         {
    15.             MasterServer.ipAddress = ipA[0].ToString();
    16.             MasterServer.port = 42000;
    17.         }
    18. Network.InitializeServer(50, Random.Range(30000,41999), !Network.HavePublicAddress());
    19. MasterServer.RegisterHost("game name", playerName + "'s Game");
    20. }
    This connects no problem. I also use a DNS getter for the web address, but other than that, nothing else here.

    And are you using the facilitator from a different URL? I use one for all, just to let you know.
     
  22. FuzzyQuills

    FuzzyQuills

    Joined:
    Jun 8, 2013
    Posts:
    2,871
    Oh, and if you need to test your code against a working server, let me know when you're going to do it, (Preferably on the weekend when I have nothing... :D) and I will fire up my master server for your testing purposes! :) From reading one of your posts, it seems you are having trouble setting up the master server, so I thought of firing up my working one for you. If you wish to do this, PM me, and I will give you the temporary no-ip.com URL I will use (I could just give out my normal address, but a test one's better for security)

    Also, where are you in the world? Must verify this first, as I host my server directly at home from an ADSL line.
     
  23. Nihil688

    Nihil688

    Joined:
    Mar 12, 2013
    Posts:
    503
    Hey thank you very much FuzzyQuills, this looks promising, I ll give it a go throughout the week with my own server and maybe I'll get it working, will let you know.

    I am still confused as to how to setup the MasterServer and Facilitator, as I said the code above is the only server I have done

    PS: I am in UK
     
  24. FuzzyQuills

    FuzzyQuills

    Joined:
    Jun 8, 2013
    Posts:
    2,871
    Right... that might be a bit far! :) (I'm in Australia) But we can give a try, nonetheless.
     
  25. Nihil688

    Nihil688

    Joined:
    Mar 12, 2013
    Posts:
    503
    You have better souvlaki there for sure :)
     
  26. FuzzyQuills

    FuzzyQuills

    Joined:
    Jun 8, 2013
    Posts:
    2,871
    Heh... maybe! :)

    BTW, may be able to put the server up! :) Just have to finish a couple of things first...