server | v3 switch to v4  

Server-To-Server Introduction

This is a tutorial for advanced developers. If you have just started to use Photon, you can safely skip this.

If you are developing a complex game, you probably want to distribute functionality between different servers. You can use Photon's Server-To-Server (S2S) features to implement the communication between your Photon servers.

Concept

S2S-communication in Photon is very similar to client-to-server-communication. One Photon instance initiates a connection (this is the "outbound" side of the connection) to the target Photon server (this is the "inbound" side of the connection). On each side, a peer is created and can be used to send operations / events over the S2S connection.

Back To Top

The Outbound / "client" Side

Let's assume you have an application "MyClientApplication", which inherits from ApplicationBase.

To initiate the S2S-connection, you need to call one of the ApplicationBase.ConnectToServerXXX methods. It is recommended to use TCP connections for S2S communication.

This code is needed to set up the S2S connection:

    
    public class MyClientApplication : ApplicationBase
    {
        private ServerPeerBase outboundPeer; 

        protected override void Setup()
        {
            this.ConnectToServerTcp(new IPEndPoint(IPAddress.Parse("123.456.789.123"), 4520), "MyMasterApplication", null); 
        }

        protected internal override ServerPeerBase CreateServerPeer(InitResponse initResponse, object state)
        {
            this.outboundPeer = new MyOutboundPeer(initResponse.Protocol, initResponse.PhotonPeer);
            return this.outboundPeer; 
        }


        protected override void OnServerConnectionFailed(int errorCode, string errorMessage, object state)
        {
            // add some custom error handling here 
        }

The above code establishes the S2S connection during Setup(). You can also do this later in your codebase, however, you should use only one connection between any two servers - keep the connection open and use that one connection to send all data through it.

If the connection can not be established, the OnServerConnectionFailed() method is called. You might want to override that method and add some error handling, logging etc. there.

If the connection is established successfully, the CreateServerPeer method is called. You need to override that method and return a ServerPeerBase-inherited object. That peer will be your client-side representation of the S2S connection. Store it in a local variable.

To send data to your target server, you simply call the SendOperation method of that peer, like this:

     
    public void SendMessageToMaster(string message)
    {
        var parameters = new Dictionary<byte, object>();
        parameters[0] = message;

        this.outboundPeer.SendOperationRequest(new OperationRequest { OperationCode = 1, Parameters = parameters }, new SendParameters());
    }

The implementation of the "OutboundPeer" class is quite simple as well. This is a minimal sample, add your own code as you see fit:


    public class MyOutboundPeer : ServerPeerBase
    {
        public MyOutboundPeer(IRpcProtocol protocol, IPhotonPeer unmanagedPeer)
            : base(protocol, unmanagedPeer)
        {
        }

        protected internal override void OnOperationRequest(OperationRequest operationRequest, SendParameters sendParameters)
        {
            // implement this if the outbound side should receive operation data
        }

        protected override void OnDisconnect(DisconnectReason reasonCode, string reasonDetail)
        {
        }

        protected internal override void OnEvent(IEventData eventData, SendParameters sendParameters)
        {
           // implement this if the outbound side should receive events
        }

        protected internal override void OnOperationResponse(OperationResponse operationResponse, SendParameters sendParameters)
        {
        }
    }

This is all that is needed on the client side of the S2S connection.

Back To Top

The "inbound" / Master Side

Now that the "client" side is done, we need to implement the "master" (or "inbound" side) of the S2S connection.

First, you need to create a peer object. To determine if the connection is from a real "client" or if it is an incoming S2S connection, it is recommended to listen to different ports.

Let's assume that you have an application that inherits from ApplicationBase. Add this code:

    
      protected override PeerBase CreatePeer(InitRequest initRequest)
        {
            if (initRequest.LocalPort == 4520)
            {
                // for S2S connections
                return new MyInboundPeer(initRequest); 
            }

            // for client-to-server connections
            return MyPeer(); 
        }

The MyInboundPeer is just a simple class that inherits of the PeerBase class:

    

    public class MyInboundPeer : PeerBase
    {
        public MyInboundPeer(InitRequest initRequest)
            : base(initRequest)
        {

        }

        protected internal override void OnOperationRequest(OperationRequest operationRequest, SendParameters sendParameters)
        {
            // implement this to receive operation data
        }

        protected override void OnDisconnect(DisconnectReason reasonCode, string reasonDetail)
        {
        }
    }

This is all that needs to be done on the "inbound" side of the S2S connection.

Back To Top

The Configuration

If you have decided to use a separate port to listen for S2S connections on the inbound side, you need to define a new listener in the PhotonServer.config, like this:


     <!-- DON'T EDIT THIS. TCP listener for S2S connections on Master application -->
    <TCPListener
        IPAddress="0.0.0.0"
        Port="4520">
    </TCPListener>

To Document Top