- Home /
Networking - MasterServer [ Connect on Lan or Wan without Internet ]
I've started to building my own multiplayer game for iOS, and It's coming together slowly but surly.
The multiplayer game is to be locally ran, so people on the same WLAN can only play it. But every time I create a closed network, I get an error 'Cannot connect to MasterServer'.
After doing some research it turns out that when you create a multiplayer game, you're actually using a Server somewhere in Unity HQ, thus needing a continues connection to the Internet.
Is it possible to use one of the iOS devices to use as a server, as well as play the game? I assumed I was already doing that, but I guess not.
Anyway, is this possible? Reason is, firstly I wont need a connection to Internet (so WLAN will work fine), and I also read that the MasterServers are really for testing only, as they are unreliable.
Any suggestions? Thanks
Just to clear some confusion. The $$anonymous$$asterServer is not the "game server". It's just a "lobby". Every player connects to the $$anonymous$$asterServer to be able to see who opened a game server. With that information, peers can connect to each other directly.
You don't need a $$anonymous$$asterServer, as long as the player know the IP and port of the game server they can connect "manually". This is how "old games" are done and even newer ones (like $$anonymous$$inecraft for example).
Next thing is only the default $$anonymous$$asterServer is ment for testing. It's hosted by UT. You are free to use it for whatever you like, but there's no guarantee it will be reachable 24/7 nor is it designed to handle millions of users so it might be overloaded at some times. That's why it's ment for testing only. If you build your own game you usually host your own dedicated $$anonymous$$asterServer online.
Pure local network discovery can only be achieved by using an UDP broadcast like flamy explained in his great answer. $$anonymous$$eep in $$anonymous$$d that certain operating systems / firewalls automatically block unknown UDP broadcasts, sometimes even routers. So there's actually no 100% reiable way.
If you want to provide the most flexible way, you should include an additional manual connect button where the user can enter the IP of the server-player.
flamy, Thanks for your comprehensive answer, which seems to be exactly what I need for server discovery for my game. However, when I try your code I get the error: "The type or namespace name `IAsyncResult' could not be found" even though I've put "using System.Net.Sockets;" at the top of the file. What am I doing wrong?
Sorry, flamy, I know I'm being really stupid, but how do you get the code you've given running in Unity? How do I run code that isn't in an object/class?
Answer by flamy · Nov 08, 2013 at 11:39 AM
Hi,
This is going to take a bit more out of u than you could actually think. First thing is for 2 system or device to connect to, you need ipadress of one another or atleast the ipadress of the host is needed by every client that wish to connect to. I have to tell my presence to everyone on the network. There are 2 ways(as I know) to tell others that I am here
1 - one way is by using a dedicated server to which i would be polling my ipaddress continously, and that dedicated server would act as a medium and give my presence to others who send their presence to the sever. This way the server would act as a medium and let others know that there is someone called flamy waiting to play from so and so address. This is a simple task. This is wat masterserver actually does. Now since it is a simple task, it comes with a limitation, you have to keep running this master server locally for others to connect to, which is highly annoying and sometimes impossible. Also the ip address of master server changes, it has to be changed in code or config file or similar. [Note: Unity provides master server source for free, you can just download it and install in one of your servers or on cloud and use it for production as well, but that is not gonna help u much if the game has to run in local.]
2 - Other way is a bit different and would be handy for you. I can keep telling everyone in the network that I am here regardless of who is listening, that way others who are on the same network would be able to know your presence if they want to look for others presence. This is cannot be done only with Unity3d classes. You need to use a technique called UDPBroadcast. This can be done using .Net framework.
So for UDPBroadcasting what has to be done is, Connect to a port on local in my machine and send certain message continuously to a remote port at certain intervals. And the remote machine will connect to the "remote port", u have sent the information to and get the information. (you can imagine port as a virtual point where data is exchanged. IF i send a data to port 100 to ipadress xxx.xxx.x.xx, only the guy who expects data from 100 will receive it.)
using System.Net.Sockets;
use this and create 2 UDP client instances, one for sending messges and one for receiving (using one is also fine but btr done seperately.)
UdpClient sender;
int remotePort = 19784;
void Start()
{
sender = new UdpClient (localPort, AddressFamily.InterNetwork);
IPEndPoint groupEP = new IPEndPoint (IPAddress.Broadcast, remotePort);
sender.Connect (groupEP);
//SendData ();
InvokeRepeating("SendData",0,5f);
}
void SendData ()
{
string customMessage = myName+" * "+myIP+" * "+myGameName;
if (customMessage != "") {
sender.Send (Encoding.ASCII.GetBytes (customMessage), customMessage.Length);
}
}
In start I am connecting to a remote port and start invoking send data after certain time (5 seconds). In send data function I am creating a parsed message including my name , ip, game name seperated by " * " note that you can use xml tags (i usually seperate like flamy ) or parser or any seperator to identity data uniquely on other end. If you have noted this line " IPEndPoint groupEP = new IPEndPoint (IPAddress.Broadcast, remotePort); ", this is what makes you send data to every connected system in network.
if still it is not clear, the strategy here is to use UDP broadcast to send my ipaddress to other and let them connect to my system using Network.Connect(); (Note: Network.connect needs ipadress of host to connect to, this udp is providing the ipaddress of the host i need the most.) and after they connect i am going to shut down this udpBroadcast thing and continue with unity only. But Until I connect, UDP is gonna be my friend.
And once sending is done I have to receive it, it is a bit more complicated and has some restrictions. Firs thing is receiving is gonna be a asynchronous process, so it will be run in a separate thread out of unity's main thread. So in this asynchronous method, you cannot use unity's static variables/methods. If used would through an error. But this can be handled easily. Well now you know the restriction, check the method to get a clear idea.
UdpClient receiver;
public void StartReceivingIP ()
{
try {
if (receiver == null) {
receiver = new UdpClient (remotePort);
receiver.BeginReceive (new AsyncCallback (ReceiveData), null);
}
} catch (SocketException e) {
Debug.Log (e.Message);
}
}
private void ReceiveData (IAsyncResult result)
{
receiveIPGroup = new IPEndPoint (IPAddress.Any, remotePort);
byte[] received;
if (receiver != null) {
received = receiver.EndReceive (result, ref receiveIPGroup);
} else {
return;
}
receiver.BeginReceive (new AsyncCallback (ReceiveData), null);
string receivedString = Encoding.ASCII.GetString (received);
}
Now parse this received string, you will have more than necessary things to connect to a server. So everyone should call StartReceivingIP (). and when you create server, you should stop receiving IP and be calling sendData().
I hope I am not confusing. Hope this would work fine for you.
Oh wait I forgot to tell you something, this will work only if the first 3 parts of the ipAdress are same 192.168.1.x and 192.168.1.y they can see each other but not 192.168.2.X well no need to worry in a same wireless netwrk, everyone will have the same address family, unless multiple routers are involved in the network. Well this aint a blocker, this can be handled. Check .Net reference when needed, I dont want to confuse by going into all that networking stuff. cheers.
PS: .Net socket class support has been removed for unity3d free licenses for Mobile versions, so UDPBroadcast wont work on iOS, android or Windows Phone Free licenses. (source: Bunny83)
Your sentence "This is cannot be done in Unity" is a bit misleading. It can be done in Unity but not with Unity classes.
Also keep in $$anonymous$$d that they removed .NET Socket support for the basic version of any Unity mobile license to use Sockets on mobile you need the pro version.
other than that +1
Wow - okay, this very helpful. This is what I'm currently using to connect: This is basically your first option right?
Network.Connect(IP, Port);
function OnConnectedToServer(){
Debug.Log("Server Joined");
SpawnPlayer();
}
This works fine as is, so whats the advantage, and disadvantage. A couple of things I do notice is that sometimes the physics (such as an Initiated missile from a rocket) can be slightly off when viewing on certain clients - but I think thats to do with the actual sync state of my code.
Okay, all is understood now - I am able to run the game on my iPad as server, and player, and then input this IP Address into the clients to connect. So now, no external servers/hosts are being used, thus I can multiplay without a connection to the outer world Internet. Thanks
@sdgd if you want to do the same through internet, it is impossible. That is where you would need a mediator like master server who will give my ip to others.
If it is Lan of 10 systems, you are sending your data to 10 systems, how big is internet, if you send data to every system connected wat would the amount of data your router has to send?!!!!! it is totally not possible. Even for lan with multiple interfaces (you can imagine 192.168.2.x is an interface and 192.168.1.x is another) it is not possible to send straight away, you need to find the list of all available interfaces and then send data to each and every interface in the same way i have done earlier. If it is internet the number of interfaces are just out of manageable count.
So internet needs something like master server or some other intermediate server, END OF STORY.
Answer by Fattie · Nov 21, 2014 at 08:11 AM
Just to complement Flamy's awesome answer...
Just TBC, this can help say during debugging or if your app is only used, say, internally by devs:
in the SERVER just use Network.player.ipAddress to get your IP address. Show it on the screen
in the client, let the human user just type that in.
Answer by lance12367 · Dec 20, 2016 at 01:05 AM
the librays you need using System.Collections; using System.Collections.Generic; using UnityEngine; using System.Net.Sockets; using System.Net; using System.Linq; using System.Text;
Your answer
Follow this Question
Related Questions
Port not opening? 3 Answers
Network.Connect not connecting to host data or ip address 1 Answer
UNET : Custom Master server question. 0 Answers