PhotonServer介绍
官网 https://www.photonengine.com/en-us/Server
Photon为您完全封装了每个客户端平台的复杂网络层。Photon Server支持可靠的UDP,TCP,HTTP和Web套接字,每种都具有精简和纤薄的传输协议。
您的游戏客户端跨平台和跨协议进行通信:只需发送数据,Photon进行反序列化/序列化。
光子服务器架构
Photon Core采用原生C ++编写,可提供最佳性能并支持一流的工具链。结合Windows Server IO完成端口(IOCP),它实现了协议的大量“提升”。
业务逻辑在.NET CLR中执行,包含用C#或任何其他.NET语言编写的应用程序。
所有应用程序都位于可扩展的RPC和事件开发框架之上,以解决常见任务。
RPC调用可以简单灵活地映射到操作实例。基于使用光纤的消息传递原理简化了线程。总的来说,Photon Server旨在在CPU成为瓶颈之前使流量饱和。
下载PhotonServer SDK
解压到非中文目录
文件夹介绍
build:
deploy:部署的服务端程序
doc:文档
lib:动态链接库 重要的有Photon3Unity3D.dll
src-server:官方提供的demo
如何启动?
根据操作系统,32位在bin win32文件夹,64位在bin win64文件夹中 运行PhotonControl.exe
免费用户只能同时链接20个用户,注册后可连接100个。在官网免费注册,下载license文件,放到PhotonControl.exe所在文件夹。
配置文件 PhotonServer.config 配置要部署的程序
<?xml version="1.0" encoding="Windows-1252"?> <!-- (c) 2015 by Exit Games GmbH, http://www.exitgames.com Photon server configuration file. For details see the photon-config.pdf. This file contains two configurations: "LoadBalancing" Loadbalanced setup for local development: A Master-server and a game-server. Starts the apps: Game, Master, CounterPublisher Listens: udp-port 5055, tcp-port: 4530, 843 and 943 --> <Configuration> <!-- Multiple instances are supported. Each instance has its own node in the config file. --> <LoadBalancing MaxMessageSize="512000" MaxQueuedDataPerPeer="512000" PerPeerMaxReliableDataInTransit="51200" PerPeerTransmitRateLimitKBSec="256" PerPeerTransmitRatePeriodMilliseconds="200" MinimumTimeout="5000" MaximumTimeout="30000" DisplayName="LoadBalancing (MyCloud)"> <!-- 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="Master"> </UDPListener> <UDPListener IPAddress="0.0.0.0" Port="5056" OverrideApplication="Game"> </UDPListener> </UDPListeners> <!-- 0.0.0.0 opens listeners on all available IPs. Machines with multiple IPs should define the correct one here. --> <TCPListeners> <!-- TCP listener for Game clients on Master application --> <TCPListener IPAddress="0.0.0.0" Port="4530" OverrideApplication="Master" PolicyFile="Policy\assets\socket-policy.xml" InactivityTimeout="10000" > </TCPListener> <TCPListener IPAddress="0.0.0.0" Port="4531" OverrideApplication="Game" PolicyFile="Policy\assets\socket-policy.xml" InactivityTimeout="10000"> </TCPListener> <!-- DON'T EDIT THIS. TCP listener for GameServers on Master application --> <TCPListener IPAddress="0.0.0.0" Port="4520"> </TCPListener> </TCPListeners> <!-- Policy request listener for Unity and Flash (port 843) and Silverlight (port 943) --> <PolicyFileListeners> <!-- multiple Listeners allowed for different ports --> <PolicyFileListener IPAddress="0.0.0.0" Port="843" PolicyFile="Policy\assets\socket-policy.xml"> </PolicyFileListener> <PolicyFileListener IPAddress="0.0.0.0" Port="943" PolicyFile="Policy\assets\socket-policy-silverlight.xml"> </PolicyFileListener> </PolicyFileListeners> <!-- WebSocket (and Flash-Fallback) compatible listener --> <WebSocketListeners> <WebSocketListener IPAddress="0.0.0.0" Port="9090" DisableNagle="true" InactivityTimeout="10000" OverrideApplication="Master"> </WebSocketListener> <WebSocketListener IPAddress="0.0.0.0" Port="9091" DisableNagle="true" InactivityTimeout="10000" OverrideApplication="Game"> </WebSocketListener> </WebSocketListeners> <!-- 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="Master"> <Application Name="Master" BaseDirectory="LoadBalancing\Master" Assembly="Photon.LoadBalancing" Type="Photon.LoadBalancing.MasterServer.MasterApplication" ForceAutoRestart="true" WatchFiles="dll;config" ExcludeFiles="log4net.config" > </Application> <Application Name="Game" BaseDirectory="LoadBalancing\GameServer" Assembly="Photon.LoadBalancing" Type="Photon.LoadBalancing.GameServer.GameApplication" ForceAutoRestart="true" WatchFiles="dll;config" ExcludeFiles="log4net.config"> </Application> <!-- CounterPublisher Application --> <Application Name="CounterPublisher" BaseDirectory="CounterPublisher" Assembly="CounterPublisher" Type="Photon.CounterPublisher.Application" ForceAutoRestart="true" WatchFiles="dll;config" ExcludeFiles="log4net.config"> </Application> </Applications> </LoadBalancing> <!-- Instance settings --> <MMoDemo MaxMessageSize="512000" MaxQueuedDataPerPeer="512000" PerPeerMaxReliableDataInTransit="51200" PerPeerTransmitRateLimitKBSec="256" PerPeerTransmitRatePeriodMilliseconds="200" MinimumTimeout="5000" MaximumTimeout="30000" DisplayName="MMO Demo" > <!-- 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="MMoDemo"> </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="MMoDemo" > </TCPListener> </TCPListeners> <!-- Policy request listener for Unity and Flash (port 843) and Silverlight (port 943) --> <PolicyFileListeners> <!-- multiple Listeners allowed for different ports --> <PolicyFileListener IPAddress="0.0.0.0" Port="843" PolicyFile="Policy\assets\socket-policy.xml" InactivityTimeout="10000"> </PolicyFileListener> <PolicyFileListener IPAddress="0.0.0.0" Port="943" PolicyFile="Policy\assets\socket-policy-silverlight.xml" InactivityTimeout="10000"> </PolicyFileListener> </PolicyFileListeners> <!-- WebSocket (and Flash-Fallback) compatible listener --> <WebSocketListeners> <WebSocketListener IPAddress="0.0.0.0" Port="9090" DisableNagle="true" InactivityTimeout="10000" OverrideApplication="MMoDemo"> </WebSocketListener> </WebSocketListeners> <!-- 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="MMoDemo"> <!-- MMO Demo Application --> <Application Name="MMoDemo" BaseDirectory="MmoDemo" Assembly="Photon.MmoDemo.Server" Type="Photon.MmoDemo.Server.PhotonApplication" ForceAutoRestart="true" WatchFiles="dll;config" ExcludeFiles="log4net.config"> </Application> <!-- CounterPublisher Application --> <Application Name="CounterPublisher" BaseDirectory="CounterPublisher" Assembly="CounterPublisher" Type="Photon.CounterPublisher.Application" ForceAutoRestart="true" WatchFiles="dll;config" ExcludeFiles="log4net.config"> </Application> </Applications> </MMoDemo> <!-- Instance settings --> <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> UDP <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> TCP <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> </Configuration>
创建第一个服务器端项目,并部署
创建类库项目
配置要求
将生成路径改为deploy/MyGameServer/bin,该文件夹位自己创建
右键项目重新生成后,查看该文件夹,发现生成MyGameServer.dll即成功
开发ApplicationBase和ClientPeer
添加引用
添加主类
/// <summary> /// 主类,启动类,类似Main() /// 所有主类都继承自ApplicationBase /// </summary> class MyGameServer : ApplicationBase { /// <summary> /// 客户端请求链接 /// </summary> /// <param name="initRequest"></param> /// <returns></returns> protected override PeerBase CreatePeer(InitRequest initRequest) { return new ClientPeer(initRequest); } /// <summary> ///server启动时 初始化 /// </summary> protected override void Setup() { throw new NotImplementedException(); } /// <summary> /// server关闭 /// </summary> protected override void TearDown() { throw new NotImplementedException(); } }
ClientPeer类
/// <summary> /// 管理跟客户端的链接 /// </summary> public class ClientPeer : Photon.SocketServer.ClientPeer { public ClientPeer(InitRequest initRequest) : base(initRequest) { } /// <summary> /// 断开链接 /// </summary> /// <param name="reasonCode"></param> /// <param name="reasonDetail"></param> protected override void OnDisconnect(DisconnectReason reasonCode, string reasonDetail) { throw new System.NotImplementedException(); } protected override void OnOperationRequest(OperationRequest operationRequest, SendParameters sendParameters) { throw new System.NotImplementedException(); } }
更改配置文件
<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>
日志文件Log
log4net
从src-server\Mmo\Photon.MmoDemo.Server复制log4net.config到项目根目录 属性设为始终复制
添加两个引用
<?xml version="1.0" encoding="utf-8" ?> <log4net debug="false" update="Overwrite"> <appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender"> <file type="log4net.Util.PatternString" value="%property{Photon:ApplicationLogPath}\\MyServer.Server.log" /> <appendToFile value="true" /> <maximumFileSize value="5000KB" /> <maxSizeRollBackups value="2" /> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%d [%t] %-5p %c - %m%n" /> </layout> </appender> <appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender"> <layout type="log4net.Layout.PatternLayout"> <param name="ConversionPattern" value="%d [%t] %-5p %c - %m%n" /> </layout> <filter type="log4net.Filter.LevelRangeFilter"> <levelMin value="DEBUG" /> <levelMax value="FATAL" /> </filter> </appender> <!-- logger --> <root> <level value="INFO" /> <!--<appender-ref ref="ConsoleAppender" />--> <appender-ref ref="RollingFileAppender" /> </root> <logger name="OperationData"> <level value="INFO" /> </logger> </log4net>
更改MyGameServer类 配置日志
using System; using System.IO; using ExitGames.Logging; using ExitGames.Logging.Log4Net; using log4net.Config; using Photon.SocketServer; namespace MyGameServer { /// <summary> /// 主类,启动类,类似Main() /// 所有主类都继承自ApplicationBase /// </summary> class MyGameServer : ApplicationBase { private static readonly ILogger log = LogManager.GetCurrentClassLogger(); /// <summary> /// 客户端请求链接 /// </summary> /// <param name="initRequest"></param> /// <returns></returns> protected override PeerBase CreatePeer(InitRequest initRequest) { log.Info("一个客户端链接过来了"); return new ClientPeer(initRequest); } /// <summary> ///server启动时 初始化 /// </summary> protected override void Setup() { //日志初始化 log4net.GlobalContext.Properties["Photon:ApplicationLogPath"] = Path.Combine(Path.Combine(this.ApplicationRootPath, "bin_Win64"), "log"); FileInfo configFileInfo=new FileInfo(Path.Combine(this.BinaryPath,"log4net.config")); if (configFileInfo.Exists) { LogManager.SetLoggerFactory(Log4NetLoggerFactory.Instance); XmlConfigurator.ConfigureAndWatch(configFileInfo); } log.Info("Setup Completed"); } /// <summary> /// server关闭 /// </summary> protected override void TearDown() { log.Info("服务端关闭"); // throw new NotImplementedException(); } } }