SuperSocket 1.4系列文档(3) 使用SuperSocket的第一步,实现你自己的AppServer和AppSession
什么是AppSession?
AppSession 代表一个和客户端的逻辑连接,基于连接的操作应该定于在该类之中。你可以用该类的实例发送数据到客户端,接收客户端发送的数据或者关闭连接。
什么是AppServer?
AppServer 代表了监听客户端连接,承载TCP连接的服务器实例。理想情况下,我们可以通过AppServer实例获取任何你想要的客户端连接,服务器级别的操作和逻辑应该定义在此类之中。
创建你的AppSession
现在,我们以EchoServer为例:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SuperSocket.SocketBase;
namespace SuperSocket.QuickStart.EchoService
{
public class EchoSession : AppSession<EchoSession>
{
public override void StartSession()
{
SendResponse("Welcome to EchoServer!");
}
public override void HandleExceptionalError(Exception e)
{
SendResponse("Server side error occurred!");
}
}
}
在此示例之中,EchoSession为我们做了两件事情:
1. 当客户端连接上时,发送欢迎信息到客户端;
2. 当命令执行的时抛出异常,发送消息"Server side error occurred!"到客户端。
创建你的AppServer
我们还是以EchoServer 为例:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SuperSocket.SocketBase;
namespace SuperSocket.QuickStart.EchoService
{
public class EchoServer : AppServer<EchoSession>
{
}
}
你的AppServer实现需要一个AppSession的类型作为泛型参数用于继承基类AppServer.因为EchoServer不需要额外的逻辑,所以不需要写任何代码在该类之中。
然后我们再以BroadcastServer 为例:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using SuperSocket.Common;
using SuperSocket.SocketBase;
using SuperSocket.SocketBase.Command;
namespace SuperSocket.QuickStart.BroadcastService
{
public class BroadcastServer : AppServer<BroadcastSession>
{
private Dictionary<string, List<string>> broadcastDict = new Dictionary<string, List<string>>(StringComparer.OrdinalIgnoreCase);
private object broadcastSyncRoot = new object();
private Dictionary<string, BroadcastSession> broadcastSessionDict = new Dictionary<string, BroadcastSession>(StringComparer.OrdinalIgnoreCase);
private object syncRoot = new object();
public BroadcastServer()
{
lock (broadcastSyncRoot)
{
//It means that device V001 will receive broadcast messages from C001 and C002,
//device V002 will receive broadcast messages from C002 and C003
broadcastDict["C001"] = new List<string> { "V001" };
broadcastDict["C002"] = new List<string> { "V001", "V002" };
broadcastDict["C003"] = new List<string> { "V002" };
}
}
internal void RegisterNewSession(BroadcastSession session)
{
if (string.IsNullOrEmpty(session.DeviceNumber))
return;
lock (syncRoot)
{
broadcastSessionDict[session.DeviceNumber] = session;
}
}
internal void RemoveOnlineSession(BroadcastSession session)
{
if (string.IsNullOrEmpty(session.DeviceNumber))
return;
lock (syncRoot)
{
broadcastSessionDict.Remove(session.DeviceNumber);
}
}
internal void BroadcastMessage(BroadcastSession session, string message)
{
List<string> targetDeviceNumbers;
lock (broadcastSyncRoot)
{
if(!broadcastDict.TryGetValue(session.DeviceNumber, out targetDeviceNumbers))
return;
}
if (targetDeviceNumbers == null || targetDeviceNumbers.Count <= 0)
return;
List<BroadcastSession> sessions = new List<BroadcastSession>();
lock (syncRoot)
{
BroadcastSession s;
foreach(var key in targetDeviceNumbers)
{
if (broadcastSessionDict.TryGetValue(key, out s))
sessions.Add(s);
}
}
Async.Run(() =>
{
sessions.ForEach(s => s.SendResponse(message));
});
}
protected override void OnAppSessionClosed(object sender, AppSessionClosedEventArgs<BroadcastSession> e)
{
RemoveOnlineSession(e.Session);
base.OnAppSessionClosed(sender, e);
}
}
}
此时,我们可以发现BroadcastServer 类中定义了许多在其他地方可以直接使用的应用程序级别的逻辑和方法。