【Unity3D】PhotonServer总结

一、PhotonServer介绍

    PhotonServer是一款服务器软件,它有它的dll,自带的服务,提供我们去使用,完成类似于Socket的功能。

二、PhotonServer的下载

    上官网,下载On-Premises的,例如我下载的是Windows版本的On-Premises系列PhotonServer。

    官网网址:https://www.photonengine.com/en/sdks

三、创建我们的Server类库

    在VS下新建一个工程,名字随意,然后在该工程下新建类库:MyServer

    接下来我们要引用如下dll

以下在解压后的PhotonServer文件夹的lib文件夹下找到

    log4net.dll:配置日志文件所需的库 (可不引入)

    Photon.SocketServer.dll:使用PhotonServer自带的服务的库(必须)

    PhotonHostRuntimeInterfaces.dll:PhontonServer服务自身需要的实时接口库(可不引入)

    ExitGames.Logging.Log4Net.dll:配置PhotonServer日志文件所需的库(可不引入)

    ExitGamesLibs.dll:PhotonServer自身需要的库(可不引入) 

------------------------------------------------------------------------------------------

这下面2个dll要分开找,一个是在MySql的C:\Program Files (x86)\MySQL\MySQL Installer for Windows(MySql.Data.dll)

、另一个是在NHibernate-5.1.3-bin下的\Required_Bins文件夹下(NHibernate.dll)(5.1.3是我下载NHibernate版本)

这是我的一个博客介绍NHibernate的 -> https://blog.csdn.net/qq_39574690/article/details/80799692

    MySql.Data.dll:连接MYSQL数据库所需的库(必须) 我那个MySql Installer for Windows文件夹找不到的话,那么可以直接在MySQL主目录下进行搜索,一般都能找到,而且有些人可能会有多个相同的dll,因为不同版本的MySql中都有这样的一个dll,所以选择好你对应的版本dll.   

    NHibernate.dll:映射数据库所需的库(可不引入)

    工程的程序集名称和默认命名空间都改为MyServer,在G:\Photon-OnPremise-Server-SDK_v4-0-29-11263\deploy\下新建一个叫MyServer的文件夹,在该文件夹下新建一个叫bin的文件夹,然后把工程的生成输出路径改为在这个bin文件夹。非常的关键这一步!

    服务器:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Photon.SocketServer;
namespace MyServer
{
    class MyServer:ApplicationBase
    {
        //接收到客户端时的调用该方法
        protected override PeerBase CreatePeer(InitRequest initRequest)
        {
            return new ClientPeer(initRequest);//直接返回一个继承于ClientPeer的对象给PhotonServer进行管理
        }
        //服务器启动后调用该方法(仅一次)
        protected override void Setup()
        {
            
        }
        //服务器关闭前调用该方法(仅一次)
        protected override void TearDown()
        {
            
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Photon.SocketServer;
namespace MyServer
{
    //一个ReceptPeer代表着一个客户端与服务器的连接,这个连接放在服务器端对它进行管理
    public class ReceptPeer : Photon.SocketServer.ClientPeer
    {
        //构造方法                                  InitRequest是初始化ClientPeer的参数,交给父类构造方法处理它
        public ReceptPeer(InitRequest initRequest) : base(initRequest)
        {
            
        }
        //该客户端断开服务器时调用
        protected override void OnDisconnect(PhotonHostRuntimeInterfaces.DisconnectReason reasonCode, string reasonDetail)
        {
            
        }
        //接收到客户端请求时调用
        protected override void OnOperationRequest(OperationRequest operationRequest, SendParameters sendParameters)
        {
            
        }
    }
}

    打开PhotonServer的配置文件(PhotonServer.config),这个文件在G:\Photon-OnPremise-Server-SDK_v4-0-29-11263\deploy\bin_Win64,用VS打开该文件。

        里面有什么我目前还不懂,也不需要弄太懂,就是把里面的<MMoDemo >... ...</MMoDemo> 的全部复制,粘贴在</Configuration>前面,然后修改为我们自己的应用程序Photon服务器端,如下:

注释我会用//来标明,复制粘贴这段代码的人注意了,要把//... 删掉!!不然会出错,在后面标注了//的都是我们要改的地方!

	<!-- Instance settings -->
	<MyGameInstance                //应用程序配置名称,随意起的 用以区分不同应用配置,因为一个PhotonServer能给多个应用程序提供服务的
		MaxMessageSize="512000"
		MaxQueuedDataPerPeer="512000"
		PerPeerMaxReliableDataInTransit="51200"
		PerPeerTransmitRateLimitKBSec="256"
		PerPeerTransmitRatePeriodMilliseconds="200"
		MinimumTimeout="5000"
		MaximumTimeout="30000"
		DisplayName="My Game"   //在PhotonSever右击出现的菜单选项的名字
		>
		
		<!-- 0.0.0.0 opens listeners on all available IPs. Machines with multiple IPs should define the correct one here. -->
		<!-- Port 5055 is Photon's default for UDP connections. -->
		<UDPListeners>
			<UDPListener
				IPAddress="0.0.0.0"
				Port="5055"
				OverrideApplication="MyGame1"> //改为我们的应用程序名,这个也是随意起的。
			</UDPListener>
		</UDPListeners>
    
		<!-- 0.0.0.0 opens listeners on all available IPs. Machines with multiple IPs should define the correct one here. -->
		<!-- Port 4530 is Photon's default for TCP connecttions. -->
		<!-- A Policy application is defined in case that policy requests are sent to this listener (known bug of some some flash clients) --> 
		<TCPListeners>
			<TCPListener
				IPAddress="0.0.0.0"
				Port="4530"
				PolicyFile="Policy\assets\socket-policy.xml"
				InactivityTimeout="10000"
				OverrideApplication="MyGame1" //改为我们的应用程序名,同上,要保证一致!				
				>
			</TCPListener>
		</TCPListeners>
	

		<!-- Defines the Photon Runtime Assembly to use. -->
		<Runtime
			Assembly="PhotonHostRuntime, Culture=neutral"
			Type="PhotonHostRuntime.PhotonDomainManager"
			UnhandledExceptionPolicy="Ignore">
		</Runtime>
				

		<!-- Defines which applications are loaded on start and which of them is used by default. Make sure the default application is defined. -->
		<!-- Application-folders must be located in the same folder as the bin_win32 folders. The BaseDirectory must include a "bin" folder. -->
		<Applications Default="MyGame1"> //Default的内容改为应用程序名
		
			<!-- MMO Demo Application -->
			<Application
				Name="MyGame1"        //应用程序名
				BaseDirectory="MyServer"    //MyServer类库的输出路径的外一层目录名称
				Assembly="MyServer"         //MyServer类库的程序集名称
				Type="MyServer.MyServer"    //指定服务器启动的是我们自己的MyServer类库,这个类库就是一个服务器。不过我们用了PhotonServer一些服务。所以启动的时候是在PhotonServer启动,而不是像我们之前那样用个控制台应用程序当服务器
				ForceAutoRestart="true"     
				WatchFiles="dll;config"
				ExcludeFiles="log4net.config">
			</Application>
		
		</Applications>
	</MyGameInstance>
	
然后保存下这个文件,注意要保存!不然也没法生效,这样,重启PhotonServer.exe当我们再次右击PhotonServer应用程序的时候会出现名叫My Game的菜单项了。PhotonServer.exe在G:\Photon-OnPremise-Server-SDK_v4-0-29-11263\deploy\bin_Win64下,因为我的是WIN64平台,所以是bin_Win64,如果是别的平台,上面的配置文件也要在相应的平台文件下找到去进行修改,配置好自己的应用服务器。

        

Unity客户端:

新建一个叫PhotonServer的物体,挂载下面C#脚本

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using ExitGames.Client.Photon;
public class PhotonEngine : MonoBehaviour,IPhotonPeerListener {


    public static PhotonEngine Instance;
    public static PhotonPeer Peer
    {
        get
        {
            return peer;
        }
    }
    private static PhotonPeer peer;
    //Debug返回时候调用
    public void DebugReturn(DebugLevel level, string message)
    {
        
    }
    //服务器直接发送Event消息给客户端,然后在这里处理
    public void OnEvent(EventData eventData)
    {
        
    }
    //客户端发送请求,服务器处理结束后发送回来的响应消息到达这里进行处理
    public void OnOperationResponse(OperationResponse operationResponse)
    {
    }

    //peer的状态发生变化的时候都会调用该方法
    public void OnStatusChanged(StatusCode statusCode)
    {
       
    }

    private void Awake()
    {
        if(Instance==null)
        {
            Instance = this;
            DontDestroyOnLoad(this.gameObject);
        }
        else if(Instance!=this)
        {
            Destroy(this.gameObject);
            return;
        }
    }
    //当有一个客户端启动游戏后就会立马进行与服务器连接
    void Start () {
        //通过Listener接收服务器端的响应 使用自带的监听器 this,使用UDP协议 ConnectionProtocol.Udp
         peer = new PhotonPeer( this , ConnectionProtocol.Udp);
        //下面的配置信息是PhotonServer.config配置文件的第三个Instance中的配置信息,即我们自己的应用程序配置信息
        //连接本地服务器PhotonServer(固定不变),UDP配置端口是5055,应用名称是MyGame1,在<Application>标签的应用名称!(若非本地的改为你服务器的IP)
        peer.Connect("127.0.0.1:5055", "MyGame1");
	}
	
	void Update () {
     
            //维持服务连接,这样才会发起连接请求Connect,以及一些信息的发送
            peer.Service();
  
	}

    void OnDestroy()
    {
        if (peer!=null && peer.PeerState == PeerStateValue.Connected)
        {
            //断开连接
            peer.Disconnect();
        }
    }
}

当我们需要发送消息给服务器时候,只需要PhotonEngine.Peer.OpCustom(byte,Dictionary<byte,object>,bool)方法发送,第一个参数是消息编号,这个消息编号会封装入接收方(服务器)的OperationRequest中,即OperationRequest.OperationCode就是它。第二个参数是参数列表,它是一个字典,第三个参数设置为true代表准必须发送消息成功,为false就尽力而为地发送消息(即发送一次,发送出去就不管了)。

当我们使用该方法发送消息出去后会在服务器端的ReceptPeer类的OnOperationRequest信息处理,它的OperationRequest就带有那个消息编号和消息参数列表,第二个参数没用过。

处理客户端请求的时候,根据消息编码的不同 用不同的处理方法,我们可以用枚举来当消息编号,在服务器端和客户端两边用一个叫Common类库,里面设置一些枚举来区分我们的各种请求。

因为,我们的参数列表是,Dictionary<byte,object>字典,所以我们又可以在Common类库下在弄一个enum来区分开不同的参数。

而又因为,我们服务器端可以直接发送Event给客户端的,所以我们再创一个enum来区分开不同的Event事件!

PhotonServer方法总结:

    1.ClientPeer类的SendEvent(EventData,SendParameters) 发送事件

参数1:EventData类

        EventData成员:Code 事件消息编号

                                   Parameters 参数列表一样是一个Dictionary<byte,object>

参数2:SendParameters(一般没有用到),若在处理客户端请求方法中的话,那么直接用方法自带的SendParameters即可,若没有外部传递来的SendParameters,那么直接new SendParameters()

    2.ClientPeer类的SendOperationResponse(OperationResponse,SendParameters) 发送响应

(注意这个方法只能在服务器端的处理请求方法中使用,如果在其他地方使用,是无效的)

参数1:OperationResponse类

            成员:

                        OperationCode 响应编号 (一般都与发送编号相同,特例除外)

                        ReturnCode  返回参数(short类型),只能保存一个参数

                        Parameters 参数列表(同上)

参数2 :SendParameters (同上)

    3.发送消息方法:PhotonPeer类的OpCustom(byte,Dictionary<byte,object>,bool)

参数1:消息编号 

参数2:发送的参数列表

参数3:保证发送成功标志位,为true表示保证发送成功,为false 则不保证。

猜你喜欢

转载自blog.csdn.net/qq_39574690/article/details/80805101
今日推荐