PhotonServer(3)
PhotonServer介绍
SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。
官网 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();
}
}
}

