什么是AppSession和AppServer
AppSession代表一个逻辑Socket连接,基于连接的操作都应该在这个类中来定义。我们可以使用AppSession向顶层的客户端发送数据,从连接接收数据或者是关闭一个连接。
AppServer是Socket服务器的实例,它坚挺着所有客户端的连接,管理所有顶层客户端的连接。理想状况下,我们可以从AppServer中找到任意一个Session。应用级的操作和逻辑应该在这里定义。
创建自己的AppSession
- Super Socket的可扩展性较高,我们可以通过继承AppSession这个类并覆盖其中的方法来创建自己的AppSession(如下面的代码)。
- 可以genju yewuxuqiu 为你的Session添加新的属性,下面我们来创建一个奖杯用于游戏服务器的AppSession。
- 与Commands的关系 第一篇文章中,提到过commands,这里再来看看。
public class TelnetSession : AppSession<telnetsession>
{
protected override void OnSessionStarted()
{
this.Send("Welcome to SuperSocket Telnet Server");
}
protected override void HandleUnknownRequest(StringRequestInfo requestInfo)
{
this.Send("Unknow request");
}
protected override void HandleException(Exception e)
{
this.Send("Application error: {0}", e.Message);
}
protected override void OnSessionClosed(CloseReason reason)
{
//添加自己需要的业务逻辑,它们将在Session关闭后被执行
base.OnSessionClosed(reason);
}
}※注意:AppSession是一个抽象类,上述方法在父类中都是空方法,不进行任何操作。这里我们不难发现,TelnetSession继承了AppSession(我是第一次见到用泛型来继承的),覆盖了父类的4个方法。OnSessionStarted方法即是在连接建立之后服务器立即向客户端发送一条欢迎信息“Welcome to SuperSocket Telnet Server”。
public class PlayerSession :AppSession<PlayerSession>
{
public int GameHallId { get; internal set; }
public int RoomId { get; internal set; }
}
public class ECHO : CommandBase<AppSession, StringRequestInfo>
{
public override void ExecuteCommand(AppSession session, StringRequestInfo requestInfo)
{
session.Send(requestInfo.Body);
}
}
在上面的代码中,不难发现,ECHO的父类是带有泛型参数(AppSession)的CommandBase。这就是其默认的AppSession。如果你想使用自己新创建的AppSession,就需要传递你自己的AppSession的类型,否则服务器是不能发现此command:
public class ECHO : CommandBase<PlayerSession, StringRequestInfo>
{
public override void ExecuteCommand(PlayerSession session, StringRequestInfo requestInfo)
{
session.Send(requestInfo.Body);
}
}
创建自己的AppServer
- 如果你想使用自己的AppSession,你必须修改你的AppServer。
- AppServer中有许多protected方法可供覆盖
public class TelnetServer : AppServer<TelnetSession>
{
}
简单说来,就是继承AppServer,并把自己定义的Session(继承AppSession)作为泛型参数。如上面代码所示,TelnetSession就可以在TelnetServer中被使用了。
public class TelnetServer : AppServer<TelnetSession>
{
protected override bool Setup(IRootConfig rootConfig, IServerConfig config)
{
return base.Setup(rootConfig, config);
}
protected override void OnStartup()
{
base.OnStartup();
}
protected override void OnStopped()
{
base.OnStopped();
}
}
好处及优点
实现自定义的AppSession和AppServer允许你按照自己的业务需求扩展SuperSocket。你可以监视(程序钩子)session的连接、关闭事件,server实例的启动和停止。你可以在AppServer的Setup()方法中读取自定义的配置。总而言之,它提供了大量用来构建你切实所需的自己的socket服务器的功能。
这次几乎又是纯翻译,其实作者已经发布了1.4的中文文档。我在这里翻译,主要是督促自己用心学习其中内容。如果我在完成其翻译后作者仍未发布1.5的中文文档,我希望能够在codeplex上更新中文文档,以尽绵薄之力。
本文中的代码我一行也没有自己调试过,觉得只要知道SuperSocket有这么回事就可以了但我一定写个小程序来试试文中的要点。我的学习方式受马士兵的影响很大,从这种学习项目的命名就可以看出。虽然我在看他的Struts2视频时,有些东西感觉不敢苟同,但这种学习方式认为还是可取的。
我已经写好了这个程序,并且调试通过了。我自定义了一个TelnetServer和TelnetSession,TelnetServer里并没有添加自己的逻辑,需要的话,一些日志记录可以放到这里。TelnetSession里添加了两个属性,覆盖了几个方法,例如覆盖了Send(string message)这个方法。创建了ECHO.cs以处理客户端的ECHO请求。以下是源码。
- TelnetServer.cs
- TelnetSession.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using SuperSocket.SocketBase; namespace SuperSocket_0200_AppServerAppSession { public class TelnetSession:AppSession<TelnetSession> { public int UserId { get; internal set; } public string Username { get; internal set; } protected override void OnSessionStarted() { this.Send("Welcome to SuperSocket Server!"); UserId = 1; Username = "test"; } public override void Send(string message) { string prefix = Username + "(" + UserId + "):"; base.Send(prefix+message); } protected override void HandleException(Exception e) { this.Send("Application error: {0}", e.Message); } protected override void OnSessionClosed(CloseReason reason) { //添加自己需要的业务逻辑,它们将在Session关闭后被执行 base.OnSessionClosed(reason); } } } - ECHO.cs
- Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SuperSocket.SocketBase;
using SuperSocket.SocketBase.Config;
namespace SuperSocket_0200_AppServerAppSession
{
public class TelnetServer:AppServer<TelnetSession>
{
protected override bool Setup(IRootConfig rootConfig, IServerConfig config)
{
return base.Setup(rootConfig, config);
}
protected override void OnStartup()
{
base.OnStartup();
}
protected override void OnStopped()
{
base.OnStopped();
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SuperSocket.SocketBase.Command;
using SuperSocket.SocketBase.Protocol;
namespace SuperSocket_0200_AppServerAppSession
{
public class ECHO:CommandBase<TelnetSession,StringRequestInfo>
{
public override void ExecuteCommand(TelnetSession session, StringRequestInfo requestInfo)
{
session.Send(requestInfo.Body);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace SuperSocket_0200_AppServerAppSession
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Press any key to start the server!");
Console.ReadKey();
Console.WriteLine();
TelnetServer appSrv = new TelnetServer();
//启动服务器
if (!appSrv.Setup(2012))//启动服务器并监听2012端口
{
Console.WriteLine("Failed to setup");
Console.ReadKey();
return;
}
Console.WriteLine();
//Try to start the appServer
if (!appSrv.Start())
{
Console.WriteLine("Failed to start!");
Console.ReadKey();
return;
}
////添加会话连接委托事件
//appSrv.NewSessionConnected += new SessionHandler(appSrv_NewSessionConnected);
////添加收到请求后的委托事件
//appSrv.NewRequestReceived += new RequestHandler(appSrv_NewRequestReceived);
Console.WriteLine("The server started successfully, press key \"q\" to stop it. ");
while (Console.ReadKey().KeyChar != 'q')
{
Console.WriteLine();
continue;
}
//Stop the appServer
appSrv.Stop();
Console.WriteLine("The server was stopped");
Console.ReadKey();
}
}
}
没有评论:
发表评论