server | v3 switch to v4  

An App From Scratch

This tutorial will try to help you understand how to build an application from scratch.

Build A Simple Chat Server In 10 Minutes.

Note: We assume you have followed the steps in "Photon in 5 Minutes" and have a locally running Photon Server.

This tutorial is thought as a first step in understanding the basics of the main concepts in Photon Application and Peer.

  • Download the Photon Server SDK and unzip it.
  • Using Visual Studio, create a new class library project ChatServer.
  • Add references to ExitGamesLibs.dll, Photon.SocketServer.dll and PhotonHostRuntimeInterfaces.dll

Now, create a new class ChatServer that inherits from Photon.SocketServer.ApplicationBase:


    using Photon.SocketServer;

    public class ChatServer : ApplicationBase
    {
        protected override PeerBase CreatePeer(InitRequest initRequest)
        {
        }

        protected override void Setup()
        {
        }

        protected override void TearDown()
        {
        }
    }

Create a new class ChatPeer that inherits from Photon.SocketServer.PeerBase:


    using Photon.SocketServer;
    using PhotonHostRuntimeInterfaces;

    public class ChatPeer : PeerBase
    {
        public ChatPeer(IRpcProtocol protocol, IPhotonPeer unmanagedPeer)
            : base(protocol, unmanagedPeer)
        {
        }

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

        protected override void OnOperationRequest(OperationRequest operationRequest, SendParameters sendParameters)
        {
        }
    }

Return a new instance of ChatPeer at ChatServer.CreatePeer:


        protected override PeerBase CreatePeer(InitRequest initRequest)
        {
            return new ChatPeer(initRequest.Protocol, initRequest.PhotonPeer);
        }

The ChatServer assembly will be loaded by Photon native core on the Default Photon instance. Thus, the server configuration file, PhotonServer.config, should contain the proper definition of that application. The following snippet illustrates an easy way to do this:

<Default [...]>
    <!-- other elements -->
    <Applications Default="ChatServer">
        <Application
            Name="ChatServer"
            BaseDirectory="ChatServer"
            Assembly="ChatServer"
            Type="ChatServer">
        </Application>
        <!-- any other applications -->
    </Applications>
    <!-- other elements -->
</Default>

This configuration requires that the server binaries are located under deploy/ChatServer/bin and that class ChatServer does not belong to a namespace. For more information about server configuration please refer to the respective documentation page.

Create a new console project for a chat client. Add reference to Photon3DotNet.dll to the new project. Client code should read as follows.


    using System;
    using System.Collections.Generic;
    using System.Text;

    using ExitGames.Client.Photon;

    public class ChatClient : IPhotonPeerListener
    {
        private bool connected;

        public static void Main()
        {
            var client = new ChatClient();
            var peer = new PhotonPeer(client, ConnectionProtocol.Tcp);

            // connect
            client.connected = false;
            peer.Connect("127.0.0.1:4530", "ChatServer");
            while (!client.connected)
            {
                peer.Service();
            }

            var buffer = new StringBuilder();
            while (true)
            {
                peer.Service();

                // read input
                if (Console.KeyAvailable)
                {
                    ConsoleKeyInfo key = Console.ReadKey();
                    if (key.Key != ConsoleKey.Enter)
                    {
                        // store input
                        buffer.Append(key.KeyChar);
                    }
                    else
                    {
                        // send to server
                        var parameters = new Dictionary<byte, object> { { 1, buffer.ToString() } };
                        peer.OpCustom(1, parameters, true);
                        buffer.Length = 0;
                    }
                }
            }
        }

        public void DebugReturn(DebugLevel level, string message)
        {
            Console.WriteLine(level + ": " + message);
        }

        public void OnEvent(EventData eventData)
        {
            Console.WriteLine("Event: " + eventData.Code);
            if (eventData.Code == 1)
            {   
                Console.WriteLine("Chat: " + eventData.Parameters[1]);
            }
        }

        public void OnOperationResponse(OperationResponse operationResponse)
        {
            Console.WriteLine("Response: " + operationResponse.OperationCode);
        }

        public void OnStatusChanged(StatusCode statusCode)
        {
            if (statusCode == StatusCode.Connect)
            {
                this.connected = true;
            }
            else
            {
                Console.WriteLine("Status: " + statusCode);
            }
        }
    }

If we now start the server the client will be able to connect and to send text messages. The server logic to process these text messages is still missing. To verify that the message was received we answer with an OperationResponse at ChatPeer.OnOperationRequest.


    protected override void OnOperationRequest(OperationRequest operationRequest, SendParameters sendParameters)
    {
        var response = new OperationResponse(operationRequest.OperationCode);
        this.SendOperationResponse(response, sendParameters);
    }

The chat client should now be able to print the event code and the chat message.

Next thing we want to do is to receive the chat messages on other clients. We implement the receiver using a publish/subscribe pattern.


    using System;
    using Photon.SocketServer;
    using PhotonHostRuntimeInterfaces;

    public class ChatPeer : PeerBase
    {
        private static readonly object syncRoot = new object();

        public ChatPeer(IRpcProtocol protocol, IPhotonPeer unmanagedPeer)
            : base(protocol, unmanagedPeer)
        {
            lock (syncRoot)
            {
                BroadcastMessage += this.OnBroadcastMessage;
            }
        }

        private static event Action<ChatPeer, EventData, SendParameters> BroadcastMessage;

        protected override void OnDisconnect(DisconnectReason disconnectCode, string reasonDetail)
        {
            lock (syncRoot)
            {
                BroadcastMessage -= this.OnBroadcastMessage;
            }
        }

        protected override void OnOperationRequest(OperationRequest operationRequest, SendParameters sendParameters)
        {
            var @event = new EventData(1) { Parameters = operationRequest.Parameters };
            lock (syncRoot)
            {
                BroadcastMessage(this, @event, sendParameters);
            }

            var response = new OperationResponse(operationRequest.OperationCode);
            this.SendOperationResponse(response, sendParameters);
        }

        private void OnBroadcastMessage(ChatPeer peer, EventData @event, SendParameters sendParameters)
        {
            if (peer != this)
            {
                this.SendEvent(@event, sendParameters);
            }
        }
    }

If you now start two clients both will be able to exchange messages. Do not forget to start Photon server or to restart it with the new configuration. Go to the documentation page if you have troubles with it.

기술문서 TOP으로 돌아가기