Understanding - an Application from the Scratch
(áka "Blank Server Tutorial")
Build a simple chat server from the scratch in 10 minutes.
Hint: This tutorial is thought as a first step in understanding the basics of the main concepts in Photon
Application and Peer. For most developers that at some point will use rooms we recommend to start with
with an application that inherits from Lite.Application.
- Download and unzip the SDK
- Create a new class library project 'ChatServer'
- Add references to ExitGamesLibs.dll, Photon.SocketServer.dll and PhotonHostRuntimeInterfaces.dll
- Create a new class 'ChatServer' and inherit 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' and inherit 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() { } 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 server configuration looks like this:
<Applications Default="ChatServer"> <Application Name="ChatServer" BaseDirectory="ChatServer" Assembly="ChatServer" Type="ChatServer" /> </Applications>This config requires that the server binaries are located under 'deploy/ChatServer/bin' and that class ChatServer does not belong to a namespace.
- Create a new console project for a chat client
- Add reference to PhotoDotNet.dll to the new project
- Client code:
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, true); // 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 start the server now the client will be able to connect and to send text messages, but 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 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 a publish/subscribe pattern:
If you now start two clients they should be able to exchange messages.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() { 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); } } }