PhotonServer

启动PhotonServer


1.下载PhotonServer:
这里写图片描述
下载地址:PhotonServer下载
2.双击解压到D盘:
这里写图片描述

3.在官网注册帐号下载免费license文件,将最大连接数由20扩展为100:
并点击PhotonControl.exe文件启动PhotonServer
这里写图片描述

4.点击Start as applicatiobn启动一个应用,点击Open Logs开启日志
这里写图片描述

5.修改PhotonServer.config文件
文件:D:\Photon-OnPremise-Server-SDK_v4-0-29-11263\deploy\bin_Win64\ PhotonServer.config
这里写图片描述


创建第一个服务器端项目,并设置部署的目录


1.使用VisualStudio2013新建一个C#的类库项目:
这里写图片描述

2.创建项目部署文件夹
在PhotonServer的deploy文件夹中创建项目文件夹(MyGameServer可变)
在MyGameServer中创建bin文件夹(固定)
这里写图片描述

3.将项目生成动态链接库(.dll)路径与项目部署路径匹配
右键项目点击属性进入项目属性设置界面
将生成项中的输出路径改为项目部署文件夹中bin的路径
这里写图片描述

4.生成项目动态链接库文件至项目部署目录
右键项目点击生成即可
这里写图片描述


开发ApplicationBase和ClientPeer


1.添加相关引用
操作:
右键项目添加引用
浏览PhotontServer目录中的lib文件夹中,添加ExitGameLibs.dll、Photon.SocketServer.dll、PhotonHostRuntimeInterfaces.dll三个引用
这里写图片描述
2.创建MyGameServer和MyClientPeer
MyGameServer:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Photon.SocketServer;

namespace MyGameServer
{
    //每个Server端主类都要继承ApplicationBase类
    public class MyGameServer:ApplicationBase
    {

        //当每个客户端连接进来的时候调用此方法
        //返回一个PeerBase对象表示一个客户端和服务器端的连接
        protected override PeerBase CreatePeer(InitRequest initRequest)
        {
            return new MyClientPeer();
        }

        //初始化时候调用
        protected override void Setup()
        {

        }

        //Server关闭的时候调用
        protected override void TearDown()
        {

        }
    }
}

MyClientPeer:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Photon.SocketServer;

namespace MyGameServer
{
    public class MyClientPeer : Photon.SocketServer.ClientPeer
    {

        //处理客户端连接断开的后续工作
        protected override void OnDisconnect(PhotonHostRuntimeInterfaces.DisconnectReason reasonCode, string reasonDetail)
        {

        }

        //处理客户端请求操作
        protected override void OnOperationRequest(OperationRequest operationRequest, SendParameters sendParameters)
        {

        }
    }
}

部署并启动第一个服务器端项目


前提:上面我们已经将项目生成至PhotonServer中创建的项目的bin目录下!
配置PhotonServer.config文件如下(直接修改示例项目的配置文件即可):

<MyGameInstance
        MaxMessageSize="512000"
        MaxQueuedDataPerPeer="512000"
        PerPeerMaxReliableDataInTransit="51200"
        PerPeerTransmitRateLimitKBSec="256"
        PerPeerTransmitRatePeriodMilliseconds="200"
        MinimumTimeout="5000"
        MaximumTimeout="30000"
        DisplayName="My Game"
        >

        <!-- 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">

            <!-- MMO Demo Application -->
            <Application
                Name="MyGame1"
                BaseDirectory="MyGameServer"
                Assembly="MyGameServer"
                Type="MyGameServer.MyGameServer"
                ForceAutoRestart="true"
                WatchFiles="dll;config"
                ExcludeFiles="log4net.config">
            </Application>


        </Applications>
    </MyGameInstance>

这里写图片描述


配置PhotonServer中日志Log4Net


1.在项目里添加log4net的配置文件(log4net.config),可以直接在PhotonServer示例项目中拷贝,拷贝至项目的根目录
这里写图片描述
修改拷贝的log4net.config文件:修改原项目名为自己的项目名

<file type="log4net.Util.PatternString" value="%property{Photon:ApplicationLogPath}\\MyGame.Server.log" />

将log4net.config文件属性设为“始终复制”:
若为“不可复制”,log4net.config文件则无法生成至PhotonServer部署目录
这里写图片描述

2.添加相关引用
这里写图片描述

3.代码:

using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Photon.SocketServer;
using ExitGames.Logging;
using ExitGames.Logging.Log4Net;
using log4net.Config;

namespace MyGameServer
{
    class MyGameServer:ApplicationBase
    {
        //获取当前的Log对象
        public static readonly ILogger log = LogManager.GetCurrentClassLogger();

        //当客户端连接过来时调用
        protected override PeerBase CreatePeer(InitRequest initRequest)
        {
            return new MyClientPeer(initRequest);
        }

        //Server启动时调用此方法
        protected override void Setup()
        {
            InitLogging();
            log.Info("==============Server Setup Complete===================");
        }
        //日志的初始化
        protected virtual void InitLogging()
        {
            log4net.GlobalContext.Properties["Photon:ApplicationLogPath"] = Path.Combine(Path.Combine(this.ApplicationRootPath, "bin_Win32"), "log");
            FileInfo configFileInfo = new FileInfo(Path.Combine(this.BinaryPath, "log4net.config"));
            if (configFileInfo.Exists)   //判断文件是否存在
            {
                LogManager.SetLoggerFactory(Log4NetLoggerFactory.Instance);  //让Photon知道使用的是log4net插件
                XmlConfigurator.ConfigureAndWatch(configFileInfo);   //让log4net插件读取配置文件
            }
        }

        //Server关闭时调用此方法
        protected override void TearDown()
        {
            log.Info("==============Server Tear Down===================");
        }

    }
}

创建Unity客户端


1.把PhotonServer中的bin目录中Photon3Unity3D.dll添加到unity客户端项目中
这里写图片描述
2.创建单例的PhotonEngine来管理和服务器端的通信

using UnityEngine;

public class PhotonEngine : MonoBehaviour {
    private static PhotonEngine Instance;    //单例

    void Awake()
    {
        if(Instance == null)
        {
            Instance = this;
            DontDestroyOnLoad(this.gameObject);
        }
        else if(Instance != this)
        {
            Destroy(this.gameObject);
            return;
        }
    }

    void Start () {

    }

    // Update is called once per frame
    void Update () {

    }
}

在客户端发起连接服务器端的请求


1.引入命名空间using ExitGames.Client.Photon;
2.实现IPhotonPeerListener 接口,实现相应方法,进行客户端监听
3.创建一个PhotonPeer 对象处理客户端与服务器端的通信,进行连接服务器端的请求
peer = new PhotonPeer(this, ConnectionProtocol.Udp);
peer.Connect(“127.0.0.1:5055”,”MyGame1”);
4.在当peer一直处于连接状态时,Update方法中一直调用peer.Service();方法
5.在OnDestory()方法中处理客户端与服务器端的断开连接操作
peer.Disconnect();

using UnityEngine;
using ExitGames.Client.Photon;
using System;

public class PhotonEngine : MonoBehaviour,IPhotonPeerListener {
    private static PhotonEngine Instance;    //单例
    private static PhotonPeer peer;

    public static PhotonPeer Peer
    {
        get
        {
            return peer;
        }
    }

    void Awake()
    {
        if(Instance == null)
        {
            Instance = this;
            DontDestroyOnLoad(this.gameObject);
        }
        else if(Instance != this)
        {
            Destroy(this.gameObject);
            return;
        }
    }

    void Start () {
        //通过Listener来接受服务器端的响应
        peer = new PhotonPeer(this, ConnectionProtocol.Udp);
        peer.Connect("127.0.0.1:5055","MyGame1");
    }

    void Update () {
        peer.Service();
    }

    void OnDestroy()
    {
        if (peer != null && peer.PeerState == PeerStateValue.Connected)
        {
            peer.Disconnect();
        }
    }

    public void DebugReturn(DebugLevel level, string message)
    {
        throw new NotImplementedException();
    }

    public void OnEvent(EventData eventData)
    {
        throw new NotImplementedException();
    }

    //当服务器response时调用此方法
    public void OnOperationResponse(OperationResponse operationResponse)
    {
        throw new NotImplementedException();
    }

    //当peer状态发生改变时调用该方法
    public void OnStatusChanged(StatusCode statusCode)
    {
        throw new NotImplementedException();
    }
}

在客户端发起请求


第一个参数(OperationCode):唯一标识此请求的Code,用来在服务器端区分不同的请求
第二个参数(OperationParams):请求时发送的数据
第三个参数:true表示数据稳定发送
PhotonEngine.Peer.OpCustom(1, data, true);

using System.Collections.Generic;
using UnityEngine;

public class Test : MonoBehaviour {

    void Start () {

    }

    void Update () {

        if (Input.GetMouseButtonDown(0))              //按下鼠标左键
        {
            Dictionary<byte, object> data = new Dictionary<byte, object>();
            PhotonEngine.Peer.OpCustom(1, data, true);
        }       
    }
}

通过SendOperationResponse带参数响应给客户端


1.operationRequest.OperationCode
服务器端通过接收客户端的OperationCode来处理相应的请求,该操作在OnOperationRequest方法里执行
2.SendOperationResponse(operationResponse, sendParameters);
服务器端响应给客户端
3.客户端在OnOperationResponse方法里接收客户端的响应,并通过operationResponse.OperationCode来区别不同的响应,进行不同的操作
服务器端(MyClientPeer):

//处理客户端请求操作
        protected override void OnOperationRequest(OperationRequest operationRequest, SendParameters sendParameters)
        {
            switch (operationRequest.OperationCode)
            {
                case 1:
                    MyGameServer.log.Info("========================receive a client reauest=============================");
                    OperationResponse operationResponse = new OperationResponse(operationRequest.OperationCode);

                    SendOperationResponse(operationResponse, sendParameters);  //response to client
                    break;

                default:
                    break;
            }
        }

客户端:

//当服务器response时调用此方法
    public void OnOperationResponse(OperationResponse operationResponse)
    {
        switch (operationResponse.OperationCode)
        {
            case 1:
                Debug.Log("receive a server response,the operationCode is " + operationResponse.OperationCode);
                break;

            default:
                break;
        }
    }

通过SendEvent带参数响应给客户端

1.SendEvent(eventData, sendParameters);
服务器端响应给客户端
2.客户端在OnEvent方法里接收客户端的响应,并通过eventData.Code来区别不同的响应,进行不同的操作
服务器端(MyClientPeer):

//处理客户端请求操作
        protected override void OnOperationRequest(OperationRequest operationRequest, SendParameters sendParameters)
        {
            switch (operationRequest.OperationCode)
            {
                case 1:
                    MyGameServer.log.Info("========================receive a client request=============================");
                    object value1; object value2;
                    Dictionary<byte, object> data1 = operationRequest.Parameters;
                    data1.TryGetValue(1, out value1);
                    data1.TryGetValue(2, out value2);
                    MyGameServer.log.Info("get data from client the data is " + value1 + " and " + value2);

                    OperationResponse operationResponse = new OperationResponse(operationRequest.OperationCode);
                    Dictionary<byte, object> data2 = new Dictionary<byte, object>();
                    data2.Add(3, "test");
                    data2.Add(4, true);

                    EventData eventData = new EventData(1);
                    eventData.SetParameters(data2);
                    SendEvent(eventData, sendParameters);
                    break;

                default:
                    break;
            }
        }

客户端:

public void OnEvent(EventData eventData)
    {
        Debug.Log("receive a eventData from server ,the eventCode is " + eventData.Code);
        switch (eventData.Code)
        {
            case 1:
                Dictionary<byte, object> data = eventData.Parameters;
                object value1, value2;
                data.TryGetValue(3, out value1);
                data.TryGetValue(4, out value2);
                Debug.Log("get value from server ,the value is " + value1 + " and " + value2);
                break;
            default:
                break;

        }
    }

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cchoop

有用的话请杯肥宅水

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值