这里通过实现聊天功能来进一步学习Photon。
上节中服务端工程中,会添加一个MyPeer类,该类继承自PeerBase。这样,在每次新的客户端连入时,都会实例化一个MyPeer。
直接先上代码在做详细解释:
- 创建一个新的类库项目”ChatServer”
- 添加引用ExitGamesLibs.dll, Photon.SocketServer.dll and PhotonHostRuntimeInterfaces.dll
- 创建一个新类的ChatServer和继承 Photon.SocketServer.ApplicationBase
using Photon.SocketServer; public class ChatServer : ApplicationBase { protected override PeerBase CreatePeer(InitRequest initRequest) { } protected override void Setup() { } protected override void TearDown() { } }
- 创建一个新的类ChatPeer并继承自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) { } }
- 在ChatServer.CreatePeer返回一个新的ChatPeer实例
protected override PeerBase CreatePeer(InitRequest initRequest) { return new ChatPeer(initRequest.Protocol, initRequest.PhotonPeer); }
- 服务器配置文件如下:
<Applications Default="ChatServer"> <Application Name="ChatServer" BaseDirectory="ChatServer" Assembly="ChatServer" Type="ChatServer" /> </Applications>
- 创建一个新的控制台项目作为聊天客户端
- 添加引用PhotoDotNet.dll
- 客户端代码:
为了验证这些信息是被接收到了,我们会在ChatPeer.OnOperationRequest响应一个OperationResponse: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); } } }
protected override void OnOperationRequest(OperationRequest operationRequest, SendParameters sendParameters) { var response = new OperationResponse(operationRequest.OperationCode); this.SendOperationResponse(response, sendParameters); }
- 接下来我们要做的就是在其他客户端接收聊天信息。我们实现了一个发布/订阅模式:
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); } } }
这里需要解释的是:
BroadcastMessage为私有静态事件,每次客户端连入初始化ChatPeer的同时,就会订阅事件。
这里this代表的就是新连入的客户端。(每次新建一个客户端,都会实例化一次ChatPeer,因此this代表新建的客户端实例)
OnBroadcastMessage中if判断语句实现不向自己发送事件,只向其他订阅了事件的对象(客户端)发送消息。