How to start a server (Specifically a LAN server) in Unity??

Options
Hello,

I was hoping there was a way to start a Photon server in Unity using code, so we can bundle our game with the server and people can run it on their computer and make LAN servers.

I am aware of the License cap of 20 ccu's but that should be enough and if they want/need more they can buy a licence and so on.

Thanks in advance!

K

Comments

  • chvetsov
    Options
    you should implement photon start your self
  • What do you mean? @chvetsov
  • chvetsov
    Options
    well, i'm not sure whether is it possible or not to start some external executable from Unity. but if it possible you need to use this way to start photon in case if your client is a server. that is it. something like Process.Start(path_to_photon);
  • @chvetsov Is there documentation on the command line args that PhotonControl.exe takes somewhere, or do you know what file I need to change to set the IP, and start the load balancing server?

    I tried to find this info but I couldn't find anything on it. Maybe I did not look in the right place?

    Thanks for the help!
  • chvetsov
    Options
    PhotonControl.exe is not right way to go.
    PhotonServer.config is place wehre you may set your address. but probably it will be ok for you just to put 0.0.0.0 there, and PhotonSocketServer.exe will listen all interfaces

    to start some configurtion from PhotonServer.config you may use PhotonSocketServer.exe /run ConfigName

    type PhotonSocketServer.exe /help to see possible commands. this is all what we have for now
  • JohnTube
    JohnTube ✭✭✭✭✭
    Options
    Hi @brainversation,

    You need to start "PhotonSocketServer.exe" and not "PhotonControl.exe".
    Download it from Photon Server SDK.

    The easiest command to start Photon:

    PhotonSocketServer.exe /run <ServerApp> /configPath <PhotonServer.config folder>

    We will add a manual on how to use it to the documentation as soon as we can.
  • @chvetsov && @JohnTube

    Thanks for the help I will attempt to do this and post my results!
  • Hello! @chvetsov && @JohnTube

    I got it to create a server and connect to a server on multiple computer!

    The downside it when I make a room on the host it makes the room and others can see it but when they try and join the room they become disconnected from the server and get an error message:

    "Receive issue. State: Connected. Server: '127.0.0.1' Exception: System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host"

    This also happens when they, the non host computer, tries to make a room.

    I looked at the logs and could not find anything that would help.

    Thanks again for your help and time, (It is almost there!)
  • brainversation
    edited August 2016
    Options
    The script I am using to start the server if it helps!

    ----------------------------------------------------------------------
    using UnityEngine;
    using System.Diagnostics;
    
    public class LANConnector : MonoBehaviour {
    	public static LANConnector instance;
    
    	Process mainProcess;
    	ProcessStartInfo startInfoServer;
    	ProcessStartInfo startInfoEnd;
    
    	void Start() {
    		if(instance) {
    			DestroyImmediate( gameObject );
    			return;
    		} else {
    			instance = this;
    		}
    
    		DontDestroyOnLoad( gameObject );
    
    		startInfoServer = new ProcessStartInfo();
    		// Configure the process using the StartInfo properties.
    		string windowsDataPath = Application.dataPath.Replace( '/', '\\' );
    		string pathToFolder = windowsDataPath + "\\..\\..\\Photon-OnPremise-Server-SDK_v4-0-29-11263\\deploy\\bin_Win64";
    		string pathToEXE = pathToFolder + "\\PhotonSocketServer.exe";
    		//string pathToConfig = pathToFolder + "\\PhotonServer.config";
    
    		startInfoServer.FileName = pathToEXE;
    		startInfoServer.Arguments = "/run LoadBalancing /configPath " + pathToFolder;
    		startInfoServer.CreateNoWindow = false;
    		startInfoServer.UseShellExecute = false;
    		startInfoServer.RedirectStandardOutput = true;
    		startInfoServer.RedirectStandardError = true;
    		//process.StartInfo.WindowStyle = ProcessWindowStyle.Maximized;
    
    		startInfoEnd = new ProcessStartInfo();
    		startInfoEnd.FileName = pathToEXE;
    		startInfoEnd.Arguments = "/stop";
    		startInfoEnd.CreateNoWindow = true;
    		startInfoEnd.UseShellExecute = false;
    	}
    
    	void Update() {
    		if(Input.GetKeyDown( KeyCode.L )) {
    			StartProcess();
    		}
    
    		if(Input.GetKeyDown( KeyCode.O )) {
    			EndProcess();
    		}
    	}
    
    	void OnApplicationQuit(){
    		if(instance) {
    			instance.EndProcess();
    		}
    	}
    
    	void StartProcess() {
    		if(mainProcess == null) {
    			print( "Start 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();
    		}
    	}
    
    	void EndProcess() {
    		print( "End Process" );
    
    		if(mainProcess != null) {
    			print( "MainProcess HasExited = " + mainProcess.HasExited );
    
    			if(!mainProcess.HasExited) {
    				print("Kill");
    				mainProcess.Kill();
    			}
    		}
    
    		mainProcess = null;
    		Process.Start( startInfoEnd );
    	}
    }
  • chvetsov
    Options
    Hi, there
    it is good news.

    i assume that problem is in GameServer config which you may find in LoadBalancing.dll.config. there is settings PublicIp. it is IP which will be send to client in order to connect to GameServer. you need to update it everytime when you start
  • brainversation
    edited August 2016
    Options
    Hello Again! @chvetsov

    It works! On my and other computers! Thank you so much for your help!

    I will post the script I used to do it after this post.

    Thanks again for your help and time!

    EDIT: How do you mark this post as answered?
  • brainversation
    edited August 2016
    Options
    The script I am using to start the server. 100% working as of this post! Thanks to the above people!

    ----------------------------------------------------------------------
    
    using UnityEngine;
    
    using System.IO;
    using System.Xml.Linq;
    using System.Diagnostics;
    
    public class LANConnector : MonoBehaviour {
    	private static LANConnector _instance;
    
    	public static bool HasInstance {
    		get {
    			return _instance;
    		}
    	}
    
    	public static LANConnector instance {
    		get {
    			create();
    			return _instance;
    		}
    
    		set {
    			_instance = value;
    		}
    	}
    
    	public static void create() {
    		if(!_instance) {
    			Instantiate( Resources.Load<LANConnector>( "LANConnector" ) );
    		}
    	}
    
    	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() {
    		if(HasInstance) {
    			UnityEngine.Debug.LogError( "There should not be two instances of this object" );
    			DestroyImmediate( gameObject );
    			return;
    		} else {
    			instance = this;
    		}
    
    		DontDestroyOnLoad( gameObject );
    
    		startInfoServer = new ProcessStartInfo();
    		// Configure the process using the StartInfo properties.
    #if UNITY_EDITOR
    		pathToRootPhotonFolder = System.Environment.GetFolderPath( System.Environment.SpecialFolder.Desktop ).Replace( '/', '\\' ) + "\\Photon-OnPremise-Server-SDK_v4-0-29-11263";
    #else
    		pathToRootPhotonFolder = Application.dataPath.Replace( '/', '\\' ) + "\\Photon-OnPremise-Server-SDK_v4-0-29-11263";
    #endif
    
    		pathToDeployFolder = pathToRootPhotonFolder + "\\deploy";
    		pathToWin64Folder = pathToDeployFolder + "\\bin_Win64";
    		pathToPhotonSocketServerEXE = pathToWin64Folder + "\\PhotonSocketServer.exe";
    		//string pathToConfig = pathToWin64Folder + "\\PhotonServer.config";
    
    		startInfoServer.FileName = pathToPhotonSocketServerEXE;
    		startInfoServer.Arguments = "/run LoadBalancing /configPath " + pathToWin64Folder;
    		startInfoServer.CreateNoWindow = false;
    		startInfoServer.UseShellExecute = false;
    		startInfoServer.RedirectStandardOutput = true;
    		startInfoServer.RedirectStandardError = true;
    		//process.StartInfo.WindowStyle = ProcessWindowStyle.Maximized;
    
    		startInfoEnd = new ProcessStartInfo();
    		startInfoEnd.FileName = pathToPhotonSocketServerEXE;
    		startInfoEnd.Arguments = "/stop";
    		startInfoEnd.CreateNoWindow = true;
    		startInfoEnd.UseShellExecute = false;
    	}
    
    #if UNITY_EDITOR
    	void Update() {
    		if(Input.GetKeyDown( KeyCode.P )) {
    			changeConfigFile();
    		}
    
    		if(Input.GetKeyDown( KeyCode.L )) {
    			StartProcess();
    		}
    
    		if(Input.GetKeyDown( KeyCode.O )) {
    			EndProcess();
    		}
    	}
    #endif
    
    	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 );
    							valueElement.SetValue( Network.player.ipAddress );
    						}
    					}
    
    					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" );
    		}
    	}
    }