Photon Server Local Network - client disconnects and reconnects every 15 seconds

Hi, I am using the Photon Server to create LAN connections. I am running the PhotonSocketServer.exe from within the game so that players can run photon server setup automatically directly from within the game. From within the game, the loadbalancing.dll.config file gets modified with the mastser client's IP address, which all the players manually input into the game. All clients can connect to the Master server's IP address no problem.

This worked for a couple weeks when I first set it up. However, recently I started having an issue that I cannot explain. After a Master server is created, when the 2nd computer connects as a client, every 15 seconds this client would disconnect. and 15 seconds later, it would be connected again. It just keeps getting connected for 15 seconds and disconnected for 15 seconds.

I would see this on the console:

When it connects:
SERVER SOCKET OUTPUT: 22:57:56,485 INFO eServer.IncomingGameServerPeer game server connection from 192.168.1.103:51160 established (id=4) [15]
SERVER SOCKET OUTPUT: 22:57:56,484 INFO ver.MasterServerConnectionBase Connecting to master at 192.168.1.103:4520, serverId=3d3379b3-e783-4210-9c54-fe64a409c46e [11]
SERVER SOCKET OUTPUT: 22:57:56,494 INFO ver.MasterServerConnectionBase Master connection established: address:192.168.1.103 [11]
SERVER SOCKET OUTPUT: 22:57:56,505 INFO oadBalancer.ServerStateManager Server state is set to online [11]
SERVER SOCKET OUTPUT: 22:57:56,515 INFO erver.OutgoingMasterServerPeer Registering game server with address 192.168.1.103, TCP 4531, UDP 5056, WebSocket 9091, Secure WebSocket 19091, HTTP 80, ServerID
SERVER SOCKET OUTPUT: 22:57:56,526 INFO erver.OutgoingMasterServerPeer Successfully registered at master server: serverId=3d3379b3-e783-4210-9c54-fe64a409c46e [13]
SERVER SOCKET OUTPUT: 22:57:56,527 INFO eServer.IncomingGameServerPeer OnDisconnect: game server connection closed (connectionId=3, serverId=b9e9daf8-41c7-4289-99f2-e668d145ef33, reason=ManagedDisconnect) [9]

---

then 15 seconds, this will show up when it disconnects:
SERVER SOCKET OUTPUT: 22:57:41,384 INFO eServer.IncomingGameServerPeer game server connection from 192.168.1.100:52952 established (id=3) [12]
SERVER SOCKET OUTPUT: 22:57:41,464 INFO eServer.IncomingGameServerPeer OnDisconnect: game server connection closed (connectionId=2, serverId=3d3379b3-e783-4210-9c54-fe64a409c46e, reason=ManagedDisconnect) [13]
SERVER SOCKET OUTPUT: 22:57:41,463 INFO erver.OutgoingMasterServerPeer connection to master closed (id=2, reason=ClientDisconnect, detail=), serverId=3d3379b3-e783-4210-9c54-fe64a409c46e [14]

I am not sure what I am doing wrong. This actually used to work without this 15 second on-off cycle. So I am not sure what is causing this issue. Been scratching my head over this issue. Appreciate your help!

Answers

  • hi, @DavidHuang

    it looks like you have two game servers which tries to connect to same master from same machine. i assume that in your logs you see that servers with ServerId=3d3379b3-e783-4210-9c54-fe64a409c46e and ServerId=b9e9daf8-41c7-4289-99f2-e668d145ef33 connect to master and kick each other.

    if it is necessary for you to use two game server, you need to update on one of them incomming ports. they are used too to index game servers on master

    best,
    ilya
  • DavidHuang
    edited June 2018
    Hi,
    Under what circumstances would I need to run more than one game server? I only have one game, so I assume I only need one game server. And I only have one GameServer folder under the loadbalancing folder, so I thought that means i would only have one game server running at any given time? But why would I have two game servers running at the same time?

    Here's is the script of how I am calling the "StartProcess" on the PhotonServerSocket.exe and how I am making changes to the config file from within the game. Am I doing something wrong here?
    public class LANConnector : MonoBehaviour
    {
        public string masterIP;
        public bool isConnection;
    
    
        public bool processStarted
        {
            get
            {
                return mainProcess != null;
            }
        }
    
        Process mainProcess;
        ProcessStartInfo startInfoServer;
        ProcessStartInfo startInfoEnd;
    
        bool changedFile;
        string pathToWin64Folder;
        string pathToDeployFolder;
        string pathToRootPhotonFolder;
        string pathToPhotonSocketServerEXE;
    
        void Awake()
        {        
            
            startInfoServer = new ProcessStartInfo();
    
            // Configure the process using the StartInfo properties.
    #if UNITY_EDITOR
            pathToRootPhotonFolder = "D:\\SteamLibrary\\steamapps\\common\\BattleSky-VR\\Photon";
    
    #else
            pathToRootPhotonFolder = Application.dataPath;
            pathToRootPhotonFolder = Directory.GetParent(pathToRootPhotonFolder).FullName;
    		pathToRootPhotonFolder = pathToRootPhotonFolder.Replace( '/', '\\' ) + "\\Photon";
            UnityEngine.Debug.Log("pathToPhotonFolder = " + pathToRootPhotonFolder);
    #endif
    
            pathToDeployFolder = pathToRootPhotonFolder.Replace('/', '\\') + "\\deploy";
            pathToWin64Folder = pathToDeployFolder.Replace('/', '\\') + "\\bin_Win64";
            pathToPhotonSocketServerEXE = pathToWin64Folder.Replace('/', '\\') + "\\PhotonSocketServer.exe";
            UnityEngine.Debug.Log("pathToPhotonFolder = " + pathToRootPhotonFolder);
            startInfoServer.FileName = pathToPhotonSocketServerEXE;
            var configPath = "\"" + pathToWin64Folder + "\"";
            print(configPath);
            startInfoServer.Arguments = "/run LoadBalancing /configPath " + configPath;
    
            startInfoServer.CreateNoWindow = false;
            startInfoServer.UseShellExecute = false;
            startInfoServer.RedirectStandardOutput = true;
            startInfoServer.RedirectStandardError = true;
            
            startInfoEnd = new ProcessStartInfo();
            startInfoEnd.FileName = pathToPhotonSocketServerEXE;
            startInfoEnd.Arguments = "/stop";
            startInfoEnd.CreateNoWindow = true;
            startInfoEnd.UseShellExecute = false;
    
            if (PlayerPrefs.GetString("lanServerIP") == "")
            {
                masterIP = LocalIPAddress();
            }
            else if (PlayerPrefs.GetString("lanServerIP") != "")
            {
                masterIP = PlayerPrefs.GetString("lanServerIP");
            }
    
        }
    
        public string LocalIPAddress()
        {
            IPHostEntry host;
            string localIP = "";
            host = Dns.GetHostEntry(Dns.GetHostName());
            foreach (IPAddress ip in host.AddressList)
            {
                if (ip.AddressFamily == AddressFamily.InterNetwork)
                {
                    localIP = ip.ToString();
                    break;
                }
            }
            return localIP;
        }
    
        void OnApplicationQuit()
        {
            if (instance)
            {
                instance.EndProcess();
            }
        }
    
        void changeConfigFile()
        {
            if (!changedFile)
            {
                if (Directory.Exists(pathToRootPhotonFolder))
                {
                    print("Changing Config File");
                    string pathy = pathToDeployFolder + "\\Loadbalancing\\GameServer\\bin\\Photon.LoadBalancing.dll.config";
                    XDocument doc = XDocument.Load(pathy, LoadOptions.PreserveWhitespace);
    
                    XElement gameServerSettings = null;
                    foreach (var g in doc.Descendants("Photon.LoadBalancing.GameServer.GameServerSettings"))
                    {
                        gameServerSettings = g;
                        break;
                    }
    
                    if (gameServerSettings != null)
                    {
                        foreach (var s in gameServerSettings.Descendants("setting"))
                        {
                            // src will be null if the attribute is missing
                            string name = (string)s.Attribute("name");
                            if (name == "MasterIPAddress" || name == "PublicIPAddress")
                            {
                                //string value = (string)s.Element( "value" );
                                //print( "Element Name: " + s.Name + " Name: " + name + " Value: " + value + " Element Value: " + s.Value );
    
                                XElement valueElement = s.Element("value");
                                print( valueElement.Name );
                                print(valueElement.Value);
                                //valueElement.SetValue(Network.player.ipAddress);
                                if (PlayerPrefs.GetString("lanServerIP") != masterIP)
                                {
                                    PlayerPrefs.SetString("lanServerIP", masterIP);
                                }
                                valueElement.SetValue(masterIP);
                                //valueElement.SetValue(LocalIPAddress());
                                //masterIP = valueElement.Value;
                            }
                        }
    
                        doc.Root.Save(pathy, SaveOptions.DisableFormatting);
                        changedFile = true;
                    }
                    else
                    {
                        UnityEngine.Debug.LogError("Could not find gameServerSettings");
                    }
                }
                else
                {
                    UnityEngine.Debug.LogError("pathToRootPhotonFolder DNE");
                }
            }
        }
    
        public void StartProcess()
        {
    
            if (processStarted)
            {
                print("Process Already Started");
            }
            else if (Directory.Exists(pathToRootPhotonFolder))
            {
                changeConfigFile();
                print("Starting Process");
    
                mainProcess = new Process();
                mainProcess.StartInfo = startInfoServer;
                mainProcess.OutputDataReceived += (sender, args) => print(string.Format("SERVER SOCKET OUTPUT: {0}", args.Data));
                mainProcess.ErrorDataReceived += (sender, args) => print(string.Format("SERVER SOCKET ERROR: {0}", args.Data));
              
                mainProcess.Start();
                mainProcess.BeginErrorReadLine();
                mainProcess.BeginOutputReadLine();
                
            }
            else
            {
                UnityEngine.Debug.LogError("pathToRootPhotonFolder DNE");
            }
        }
    
        public void EndProcess()
        {
            if (Directory.Exists(pathToRootPhotonFolder))
            {
                print("Ending Process");
    
                if (mainProcess != null)
                {
                    print("MainProcess HasExited = " + mainProcess.HasExited);
    
                    if (!mainProcess.HasExited)
                    {
                        print("Kill");
                        mainProcess.Kill();
                    }
                }
    
                mainProcess = null;
                Process.Start(startInfoEnd);
            }
            else
            {
                UnityEngine.Debug.LogError("pathToRootPhotonFolder DNE");
            }
        }
    }
  • well, the code looks ok. Let's take a look at log files you have. you may take them from bin_Win64/log and from deploy/log folders

    best,
    ilya
  • @DavidHuang i did not found logs from game server and master server. what you provided is only native code logs

    best,
    ilya
  • Hi, I just put the GSGAme and MSMAster logs in the same folder. please take a look. thanks,
  • hi, @DavidHuang

    I see that you have game server restart. it happens because after start you update config. Although restart functionality is there we do not recommend to use it and do not use it our selves.
    Please consider changing your code so, that it updates config before starting photon

    best,
    ilya
  • Hi, I changed the code so that the config gets changed first, and then I invoke the StartProcess method 5 seconds after that. But I am still getting the 15 seconds on and off just like before... What else could be causing this?
  • JohnTube
    JohnTube ✭✭✭✭✭
    edited June 2018
    Hi @DavidHuang,

    Thank you for choosing Photon!

    I invite you to read these pages from our documentation:

    - "Analyzing Disconnects"
    - "Client Connection Handling"

    And also the answer to the question "Why are my clients disconnecting? How can I debug timeouts?".

    Next time, please properly format code or for long code blocks share a link to file or online snippet (e.g. hastebin).
  • @DavidHuang send me new logs, I will check them again on Monday.
    Please clean up all old stuff from logs

    best,
    ilya