6-15 Using Handler To Respond Requisition In Photon Server
本章繼續完成Server端處理Request的部分,基本概念與Client端差不多,只不過在Server時將用詞轉換成Handler。由於本章已經預先完成許多類別了,如果有直接跳到本章節進來看的朋友,建議先從6-1開始看比較好唷。
首先定義BaseHandler,一樣要有OperationCode,然後定義抽象方法OnOperationRequest。
接著撰寫LoginHandler去處理Client端傳來的Login Request,在建構子中先定義opercationCode為Login。
接著就可以覆寫OnOperationRequest,然後再方法內實作與資料庫驗證帳號密碼的動作。
使用我們前幾章寫好的UserManager,內部會處理跟User有關的資料庫操作。然後要特別注意的是,這邊我們使用了ReturnCode,這是由Photon定義的可供傳送小資訊(short)的參數,畢竟不是每一次Responce都需要建立一個Dictionary回傳吧。好比這次處理登入的事件,只需回傳Success或Failed即可。
接著,雖然ReturnCode是short型別,建議還是弄個enum去管理。
接著在NoliahFantasyServer.cs的主類別中新增LoginHandler,並將之Add進Dictionary中進行管理。
在MyClientPeer.cs中的OnOperationRequest中便能夠直接呼叫,先從operationRequest.OperationCode中取得byte碼,再從NoliahFantasyServer的Handler Dictionary中取得對應的BaseHandler,呼叫BaseHandler內的OnOperationRequest進行處理。
底下提供Server端本次修改的完整原始碼。
NoliahFantasyServer.cs:
BaseHandler.cs:
LoginHandler.cs:
MyClientPeer.cs:
ReturnCode.cs:
接下來繼續修改Client端,處理從Server傳回的Response。由於登入部分的處理涉及『場景切換』以及『顯示提示訊息』這兩個與UI比較相關的工作,所以我將這部分的處理劃分到LoginWindow.cs中。
接著在LoginWindow.cs中處理OnLoginResponse,失敗的話應有提示訊息顯示『帳號或密碼錯誤』,成功的話應要跳轉場景,但本章就先顯示個『登入成功』就好了。
以下提供原始碼:
LoginRequest.cs:
LoginWindow.cs:
接著來測試遊戲吧,首先輸入錯誤的帳號密碼。
再來輸入正確的帳號密碼,嗯,成功了!
首先定義BaseHandler,一樣要有OperationCode,然後定義抽象方法OnOperationRequest。
接著撰寫LoginHandler去處理Client端傳來的Login Request,在建構子中先定義opercationCode為Login。
接著就可以覆寫OnOperationRequest,然後再方法內實作與資料庫驗證帳號密碼的動作。
使用我們前幾章寫好的UserManager,內部會處理跟User有關的資料庫操作。然後要特別注意的是,這邊我們使用了ReturnCode,這是由Photon定義的可供傳送小資訊(short)的參數,畢竟不是每一次Responce都需要建立一個Dictionary回傳吧。好比這次處理登入的事件,只需回傳Success或Failed即可。
接著,雖然ReturnCode是short型別,建議還是弄個enum去管理。
接著在NoliahFantasyServer.cs的主類別中新增LoginHandler,並將之Add進Dictionary中進行管理。
在MyClientPeer.cs中的OnOperationRequest中便能夠直接呼叫,先從operationRequest.OperationCode中取得byte碼,再從NoliahFantasyServer的Handler Dictionary中取得對應的BaseHandler,呼叫BaseHandler內的OnOperationRequest進行處理。
底下提供Server端本次修改的完整原始碼。
NoliahFantasyServer.cs:
using System;
using System.IO;
using System.Collections.Generic;
using Photon.SocketServer;
using ExitGames.Logging;
using ExitGames.Logging.Log4Net;
using log4net.Config;
using NHibernate;
using NHibernate.Cfg;
using NoliahFantasyServer.Constant;
using NoliahFantasyServer.Handler;
using NoliahFantasyServer.Model;
using NoliahFantasyServer.Manager;
namespace NoliahFantasyServer
{
public class NoliahFantasyServer : ApplicationBase
{
public static readonly ILogger logger = LogManager.GetCurrentClassLogger();
public static Dictionary handlerDict =
new Dictionary();
// 當Client端發出Request的時候
protected override PeerBase CreatePeer(InitRequest initRequest)
{
return new MyClientPeer(initRequest);
}
// Server端啟動的時候初始化
protected override void Setup()
{
InitLogger();
InitHandler();
}
// Server端關閉的時候
protected override void TearDown()
{
}
void InitLogger()
{
// 日誌初始化
log4net.GlobalContext.Properties["Photon:ApplicationLogPath"] =
Path.Combine(this.ApplicationRootPath, "bin_Win64", "log");
FileInfo loggerConfig = new FileInfo(Path.Combine(this.BinaryPath, "log4net.config"));
if (loggerConfig.Exists)
{
// 設置使用log4net的Log功能
LogManager.SetLoggerFactory(ExitGames.Logging.Log4Net.Log4NetLoggerFactory.Instance);
// 讓log4net讀取config
XmlConfigurator.ConfigureAndWatch(loggerConfig);
}
logger.Info("Setup Log4Net Compeleted!");
}
void InitHandler(){
LoginHandler loginHandler = new LoginHandler();
handlerDict.Add(loginHandler.operationCode, loginHandler);
}
}
}
BaseHandler.cs:
using System;
using Photon.SocketServer;
using NoliahFantasyServer.Constant;
namespace NoliahFantasyServer.Handler
{
public abstract class BaseHandler
{
public OperationCode operationCode;
public abstract void OnOperationRequest(OperationRequest operationRequest,
SendParameters sendParameters,
ClientPeer clientPeer);
}
}
LoginHandler.cs:
using System;
using Photon.SocketServer;
using NoliahFantasyServer.Constant;
using NoliahFantasyServer.Manager;
namespace NoliahFantasyServer.Handler
{
public class LoginHandler : BaseHandler
{
public LoginHandler(){
operationCode = OperationCode.Login;
}
public override void OnOperationRequest(OperationRequest operationRequest, SendParameters sendParameters, ClientPeer clientPeer)
{
// 從OperationRequest取得帳號密碼資訊
object account;
operationRequest.Parameters.TryGetValue((byte)ParameterCode.Acccount, out account);
object password;
operationRequest.Parameters.TryGetValue((byte)ParameterCode.Password, out password);
// 使用UserManager向資料庫驗證使用者的帳號密碼
UserManager userManager = new UserManager();
bool isVerify = userManager.VerifyUser(account as string, password as string);
// 使用short類型的ReturnCode簡單回傳結果
OperationResponse operationResponse = new OperationResponse((byte)OperationCode.Login);
if(isVerify){
operationResponse.ReturnCode = (short)ReturnCode.Success;
}else{
operationResponse.ReturnCode = (short)ReturnCode.Failed;
}
// 發送Response
clientPeer.SendOperationResponse(operationResponse, sendParameters);
}
}
}
MyClientPeer.cs:
using System;
using System.Collections;
using System.Collections.Generic;
using Photon.SocketServer;
using PhotonHostRuntimeInterfaces;
using NoliahFantasyServer.Handler;
using NoliahFantasyServer.Constant;
namespace NoliahFantasyServer
{
public class MyClientPeer : ClientPeer
{
const int SIGNUP = 1;
const int BROADCAST = 2;
public MyClientPeer(InitRequest initRequest) : base(initRequest)
{
}
// Client端斷開連結的時候
protected override void OnDisconnect(DisconnectReason reasonCode, string reasonDetail)
{
}
// 處理Client的Request請求
protected override void OnOperationRequest(OperationRequest operationRequest, SendParameters sendParameters)
{
BaseHandler baseHandler = null;
NoliahFantasyServer.handlerDict.TryGetValue((OperationCode)operationRequest.OperationCode, out baseHandler);
baseHandler.OnOperationRequest(operationRequest, sendParameters, this);
}
}
}
ReturnCode.cs:
using System;
namespace NoliahFantasyServer.Constant
{
public enum ReturnCode : short
{
Success,
Failed
}
}
接下來繼續修改Client端,處理從Server傳回的Response。由於登入部分的處理涉及『場景切換』以及『顯示提示訊息』這兩個與UI比較相關的工作,所以我將這部分的處理劃分到LoginWindow.cs中。
接著在LoginWindow.cs中處理OnLoginResponse,失敗的話應有提示訊息顯示『帳號或密碼錯誤』,成功的話應要跳轉場景,但本章就先顯示個『登入成功』就好了。
以下提供原始碼:
LoginRequest.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using ExitGames.Client.Photon;
public class LoginRequest : Request {
[HideInInspector] public string account;
[HideInInspector] public string password;
LoginWindow loginWindow;
void Start(){
base.Start ();
loginWindow = GetComponent ();
}
public override void OnDefaultRequest ()
{
Dictionary data = new Dictionary ();
data.Add((byte)ParameterCode.Acccount, account);
data.Add((byte)ParameterCode.Password, password);
// 向Server發出Request,true代表建立可靠連接
PhotonEngine.Instance.GetPeer().OpCustom((byte)operationCode, data, true);
}
public override void OnOperationResponse (OperationResponse operationResponse)
{
ReturnCode returnCode = (ReturnCode)operationResponse.ReturnCode;
loginWindow.OnLoginResponse (returnCode);
print (operationResponse.ReturnCode);
}
}
LoginWindow.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
public class LoginWindow : Panel {
[SerializeField] SignupWindow signupWindow;
[SerializeField] InputField accountInput;
[SerializeField] InputField passwordInput;
[SerializeField] Text hintText;
LoginRequest loginRequest;
void Start(){
base.Start ();
loginRequest = GetComponent ();
}
public void OnLoginButton(){
hintText.text = string.Empty;
// 設定帳號及密碼參數後,呼叫OnDefaultRequest發送Request給Photon
loginRequest.account = accountInput.text;
loginRequest.password = passwordInput.text;
loginRequest.OnDefaultRequest ();
}
public void OnShowSignupButton(){
this.Hide ();
signupWindow.Show ();
}
public void OnLoginResponse(ReturnCode returnCode){
if (returnCode == ReturnCode.Success) {
hintText.text = "登入成功";
} else {
hintText.text = "帳號或密碼錯誤";
}
}
}
接著來測試遊戲吧,首先輸入錯誤的帳號密碼。
再來輸入正確的帳號密碼,嗯,成功了!











留言
張貼留言