How to use ServerToServer?

kyoku
edited June 2011 in Photon Server
Is there server-to-server sample or tutorial?

I want to independent the lobby server and each game logic server, I guess ServerToServer could help me transmission info between multi servers , I has read developer network and Photon SocketServer document, But I can't find more information to learning this technology.

Comments

  • can someone tell me how to solve this problem?

    I must be completed as soon as assessment which Game Server for my company. I do not want to use socket of .netframework, if I used that, I have to maintain socket packet of broken and stick by myself, It's very cumbersome.

    I had tried to use ServerToServer, But I'm not sure the method correctly or not, I created a new service named LoadBalancer, entry point is application. I guess the client is used TcpClient to connect LoadBalancer. I created listener with TcpBinaryReader in LoadBalancer.

    Code of application:
        public class EZLoadBalancerApplication : Application
        {
            protected override IPeer CreatePeer(PhotonPeer photonPeer, InitRequest initRequest)
            {
                // Create photonPeer
                return new EZLoadBalancerPeer(photonPeer);
            }
    
            protected override void Setup()
            {
                // Init Log operation
                LogManager.SetLoggerFactory(Log4NetLoggerFactory.Instance);
    
                // log4net
                XmlConfigurator.ConfigureAndWatch(new FileInfo("bin\\log4net.config"));
            }
    
            protected override void TearDown()
            {
                //throw new NotImplementedException();
            }
        }
    ........
    


    Code of peer :
        public class EZLoadBalancerPeer : TcpBinaryReader, IPeer 
        {
            private readonly PhotonPeer photonPeer;
            private readonly IFiber fiber;
    
            private static readonly ILogger log = LogManager.GetCurrentClassLogger();
    
            public EZLoadBalancerPeer(PhotonPeer photonPeer)
            {
                this.photonPeer = photonPeer;
                this.fiber = new PoolFiber();
                this.fiber.Start();
            }
    
    
            public void OnDisconnect()
            {
    
            }
    
            public void OnOperationRequest(OperationRequest request)
            {
                try
                {
                    log.DebugFormat("request={0}", request);
                }
                catch (Exception EX)
                {
                    log.ErrorFormat("request : " + EX.Message);
                }
            }
    
            public PhotonPeer PhotonPeer
            {
                get { return this.photonPeer; }
            }
    
            //////////////////////////////////////////////////////////////////////////////////
    
            protected override void OnEvent(EventData eventData)
            {
                try
                {
                    log.DebugFormat("eventData={0}", eventData);
                }
                catch (Exception EX)
                {
                    log.ErrorFormat("OnEvent : " + EX.Message);
                }
            }
    
            protected override void OnInitResponse(byte[] data)
            {
                //throw new NotImplementedException();
            }
    
            protected override void OnOperationResponse(OperationResponse operationResponse)
            {
                try
                {
                    log.DebugFormat("operationResponse={0}", operationResponse);
                }
                catch (Exception EX)
                {
                    log.ErrorFormat("operationResponse : " + EX.Message);
                }
            }
    
            protected override void OnPingResponse(PingResponse pingResponse)
            {
                //throw new NotImplementedException();
            }
        }
    


    and plug into PhotonServer.config
    .....
    		<TCPLoadBalancerListeners>
    			<TCPListener
    				IPAddress="0.0.0.0"
    				Port="5888"
    				Application="EZLoadBalancer"
    				InactivityTimeout="5000">
    			</TCPListener>
    		</TCPLoadBalancerListeners>
    
    .....
    
    			<!-- EZ LoadBalancer Service -->
    			<Application
    				Name="EZLoadBalancer"
    				BaseDirectory="EZLoadBalancer"
    				Assembly="EZLoadBalancer"
    				Type="EZLoadBalancer.EZLoadBalancerApplication"
    				EnableAutoRestart="true"
    				WatchFiles="dll;config"
    				ExcludeFiles="log4net.config">
    			</Application>
    .....
    



    Finally, I'm connected to LoadBalancer from the Game Server and send a message.
        public class EZServerPeer : IPeer
        {
            private readonly PhotonPeer photonPeer;
            private readonly IFiber fiber;
            private readonly Photon.SocketServer.ServerToServer.TcpClient tc;
    
            private static readonly ILogger log = LogManager.GetCurrentClassLogger();
    
            public EZServerPeer(PhotonPeer photonPeer)
            {
                this.photonPeer = photonPeer;
                this.fiber = new PoolFiber();
                this.fiber.Start();
    
    
                // connecting to loadbalancer
                IPAddress TargetIP = IPAddress.Parse("127.0.0.1");
                int TargetPort = 5888;
                IPEndPoint TargetIEP = new IPEndPoint(TargetIP, TargetPort);
                tc = new Photon.SocketServer.ServerToServer.TcpClient(TargetIEP, "EZLoadBalancer");
                tc.Connect();
    
    
                // send a message to loadbalancer
                var parameter = new Dictionary<short, object> { 
                                                  { 1, "test" }
                                               };
                var eventData = new EventData(
                    (short)EventCode.LoginEvent,
                    parameter,
                    Reliability.Reliable, 
                    0, 
                    false); 
    
                tc.SendEvent(eventData);
            }
    
    ........
    
    
    

    But LoadBalancer did not work.
    i'm not sure that's my ideas completely wrong or just usage incorrect .
  • Kyoku, we don't have have sample code for Server-to-Server yet. So far, it's a solution which works but does not feel good enough yet, so we want to polish this before we document it.

    From what I can see, your config is wrong. The server does not know your node TCPLoadBalancerListeners. It must be a TCPListener in the TCPListeners node as any other application.
    	<TCPListeners>
    		<!-- TCP listener for Game clients -->
    		<TCPListener
    			IPAddress="0.0.0.0"
    			Port="4530"
    			DisableNagle="true"
    			InactivityTimeout="0">
    		</TCPListener>
    		
    		<!-- TCP listener for GameServer clients -->
    		<TCPListener
    			IPAddress="0.0.0.0"
    			Port="4520"
    			DisableNagle="true"
    			InactivityTimeout="0">
    		</TCPListener>
    	</TCPListeners>
    

    The "GameServer clients" are other Photons that will communicate with a master / loadbalancer.
  • The TcpClient.Connect method is an asynchronous operation.
    The ConnectCompleted event is raised when the connect completed successfully. If an error occures during the connect the ConnectError event will be raised. Messages could only be sent after ConnectCompleted was raised.
    The SendEvent method is currently not supported. You should use SendOperationRequest to sent messages to the load balancer.
    At the load balancer site operation requests will be handled by the common IPeer implementation. You don’t have to inheritate from TcpBinaryReader
      public class EZServerPeer : IPeer
        {
            private readonly PhotonPeer photonPeer;
            private readonly IFiber fiber;
            private readonly Photon.SocketServer.ServerToServer.TcpClient tc;
    
            private static readonly ILogger log = LogManager.GetCurrentClassLogger();
    
            private Photon.SocketServer.ServerToServer.TcpClient tcpClient;
    
            public EZServerPeer(PhotonPeer photonPeer)
            {
                this.photonPeer = photonPeer;
                this.fiber = new PoolFiber();
                this.fiber.Start();
    
    
                // connecting to loadbalancer
                IPAddress TargetIP = IPAddress.Parse("127.0.0.1");
                int TargetPort = 5888;
                IPEndPoint TargetIEP = new IPEndPoint(TargetIP, TargetPort);
                this.tcpClient = new Photon.SocketServer.ServerToServer.TcpClient(TargetIEP, "EZLoadBalancer");
                this.tcpClient.ConnectCompleted += this.tcpClient_ConnectCompleted;
                this.tcpClient.ConnectError += this.tcpClient_ConnectError;
                
                tc.Connect(); 
            }
    
            private void  tcpClient_ConnectError(object sender, SocketErrorEventArgs e)
            {
                //An error occured during the connect attemp
                log.ErrorFormat("Error during connect: error = {0}", e.SocketError);
            }
    
            private void  tcpClient_ConnectCompleted(object sender, EventArgs e)
            {
                //TcpClient is now connected to the load balancer
                // send a message to loadbalancer
                var parameter = new Dictionary<short, object> { { 1, "test" } };
                short operationCode = 10;
                tcpClient.SendOperationRequest(operationCode, parameter);
            }
    
    public class EZLoadBalancerPeer : IPeer 
    {
    	// operation request from the game server will go here
    	public void OnOperationRequest(OperationRequest request)
    	{
    		try
    		{
    			log.DebugFormat("request={0}", request.OperationCode);
    		}
            catch (Exception EX)
            {
    			log.ErrorFormat("request : " + EX.Message);
            }
        }
    }
    
  • I have successfully used the ServerToServer, thank you very much.
    public EZServerPeer(PhotonPeer photonPeer)
            {
                this.photonPeer = photonPeer;
                this.fiber = new PoolFiber();
                this.fiber.Start();
    
                IPAddress TargetIP = IPAddress.Parse("127.0.0.1");
                int TargetPort = 5888;
                IPEndPoint TargetIEP = new IPEndPoint(TargetIP, TargetPort);
    
                this.tcpClient = new Photon.SocketServer.ServerToServer.TcpClient(TargetIEP, "EZLoadBalancer");
                this.tcpClient.ConnectCompleted += this.tcpClient_ConnectCompleted;
                this.tcpClient.ConnectError += this.tcpClient_ConnectError;
                this.tcpClient.OperationResponse += this.tcpClient_OperationResponse;
                this.tcpClient.Event += tcpClient_Event;
    
    
                tcpClient.Connect();
    
    
            }
    
    
    
    
            private void tcpClient_ConnectError(object sender, SocketErrorEventArgs e)
            {
                //An error occured during the connect attemp
                log.ErrorFormat("Error during connect: error = {0}", e.SocketError);
            }
    
            private void tcpClient_ConnectCompleted(object sender, EventArgs e)
            {
                //TcpClient is now connected to the load balancer
                // send a message to loadbalancer
                var parameter = new Dictionary<short, object> { { 1, "test" } };
                short operationCode = 10;
                tcpClient.SendOperationRequest(operationCode, parameter);
            }
    
    
            private void tcpClient_OperationResponse(object sender, OperationResponseEventArgs e)
            {
                try
                {
                    log.DebugFormat("tcpClient_OperationResponse={0}", e.OperationResponse.OperationCode);
                }
                catch (Exception EX)
                {
                    log.ErrorFormat("tcpClient_OperationResponse : " + EX.Message);
                }
            }
    
            private void tcpClient_Event(object sender, EventDataEventArgs e)
            {
                try
                {
                    log.DebugFormat("tcpClientEvent={0}", e.EventData.EventCode);
                }
                catch (Exception EX)
                {
                    log.ErrorFormat("tcpClient_Event : " + EX.Message);
                }
    
            }
    


    I will always attention the update status of this feature. thank you very much.
  • Tobias wrote:
    Kyoku, we don't have have sample code for Server-to-Server yet. So far, it's a solution which works but does not feel good enough yet, so we want to polish this before we document it.

    any Idea when this will be done? I'd like to use it as well, because I will rely on multiple Servers for my game. Would you recommend playing with it now as Kyoku did or wait until you've polished it out?

    Thanks.

    -Seb
  • We send out a Load Balancing package on request (mail to: developer at exitgames com) but the "public" one is maybe a month ahead.

    It is a good idea to spend some time with this early package, if you have some experience as developer. As the basic principles won't be changed, it's not wasted time but if you are still struggling with multiplayer development or even with C#, then it might cost you more time than necessary, I'd say.

    In the end, the package will hopefully make the transition relatively painless, so I wouldn't worry about a distributed server farm, until you know how your game performs on a single game server. Aside from adding a "master" server which distributes the players to servers, each individual game server will behave a lot like it's alone. It's worth getting a single machine running well.
  • Alright thank you for the detailed answer.
    The single Server is running smoothly for 3 weeks now without any hiccup - testwise I am sending messages permanently around & store / delete database records on random occasions while connecting with the development client at the same time and I cannot see any leaks in performance.

    Thanks again.

    -Seb