牛骨文教育服务平台(让学习变的简单)
博文笔记

SuperSocket服务器架设(四):我的AppSession连接管理方案(简单版)

创建时间:2013-12-12 投稿人: 浏览次数:7398

1.        AppSession连接管理的用处:

a)        服务器向客户端批量推送信息

b)       客户端对客户端的通信

 

2.        创建客户端管理类MySessionManager,添加静态列表SessionList

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;

namespace SuperSocketApp1
{
    /// <summary>
    /// MySession对应连接储存类
    /// </summary>
    public static class MySessionManager
    {
        public static List<MySession> SessionList = new List<MySession>();
    }
}

3.        SessionList的添加与移除方法1:

a)        在MySession的OnSessionStarted()方法中添加如下代码

MySessionManager.SessionList.Add(this);

 

b)       在MySession的OnSessionClosed()方法中添加如下代码

MySessionManager.SessionList.Remove(this);

4.        SessionList的添加与移除方法2:

a)        在MyServer的OnNewSessionConnected()方法中添加如下代码

MySessionManager.SessionList.Add(session);

b)       在MyServer的OnSessionClosed()方法中添加如下代码

MySessionManager.SessionList.Remove(session);

5.        向客户端推送消息的代码可以自由发挥,比如以自定义命令的方式实现:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SuperSocket.SocketBase;
using SuperSocket.SocketBase.Command;
using SuperSocket.SocketBase.Protocol;

namespace SuperSocketApp1
{
    /// <summary>
    /// 向客户端推送信息
    /// </summary>
    public class PUSH : CommandBase<MySession, StringRequestInfo>
    {
        public override void ExecuteCommand(MySession session, StringRequestInfo requestInfo)
        {
            /* 
             * 内置命令行协议:
             *      命令行协议定义了每个请求必须以回车换行结尾 "
"。
             *      用空格来分割请求的Key和参数
             *      requestInfo.Body 参数
             *      requestInfo.Parameters 用空格分隔参数,返回数组
             */
            foreach (MySession tmp in MySessionManager.SessionList)
            {
                tmp.Send(requestInfo.Body);
            }
        }
    }
}

6.        客户端间的通信过程为:获取客户端列表,选择客户端并发送消息(这里通过自定义命令实现)

a)        获取客户端列表:创建LIST命令,代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SuperSocket.SocketBase;
using SuperSocket.SocketBase.Command;
using SuperSocket.SocketBase.Protocol;

namespace SuperSocketApp1
{
    public class LIST : CommandBase<MySession, StringRequestInfo>
    {
        /// <summary>
        /// 获取客户端列表
        /// </summary>
        /// <param name="session"></param>
        /// <param name="requestInfo"></param>
        public override void ExecuteCommand(MySession session, StringRequestInfo requestInfo)
        {
            var tmp = "";
            //判断clentList中是否有值
            if (MySessionManager.SessionList.Count < 1)
            {
                tmp = "NoBody.";
            }
            else
            {
                for (int i = 0; i < MySessionManager.SessionList.Count; i++)
                {
                    //SessionID为Session的唯一标示
                    tmp += "Id:" + (i + 1) + ",SessionID:" + MySessionManager.SessionList[i].SessionID;
                }
            }
            session.Send(tmp);
        }
    }
}


b)       选择客户端并发送消息:创建SEND命令,代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SuperSocket.SocketBase;
using SuperSocket.SocketBase.Command;
using SuperSocket.SocketBase.Protocol;

namespace SuperSocketApp1
{
    /// <summary>
    /// 向客户端推送信息
    /// </summary>
    public class SEND : CommandBase<MySession, StringRequestInfo>
    {
        public override void ExecuteCommand(MySession session, StringRequestInfo requestInfo)
        {
            /* 
             * 内置命令行协议:
             *      命令行协议定义了每个请求必须以回车换行结尾 "
"。
             *      用空格来分割请求的Key和参数
             *      requestInfo.Body 参数
             *      requestInfo.Parameters 用空格分隔参数,返回数组
             */
            //通过参数的个数判断命令类型
            if (requestInfo.Parameters.Length < 2)
            {
                session.Send("命令格式:send id 信息");
                //send 信息
                //for (int i = 0; i < Client.clientList.Count; i++)
                //{
                //    //取SessionId对应的Session并发送信息
                //    Client.TestServer.GetAppSessionByID(Client.clientList[i]).Send(requestInfo.Body);
                //}
            }
            else
            {
                //send id 信息
                //判断id是否合法
                if (int.Parse(requestInfo.Parameters[0]) < 1 || int.Parse(requestInfo.Parameters[0]) > MySessionManager.SessionList.Count)
                {
                    session.Send("id错误。");
                }
                else
                {
                    int i = int.Parse(requestInfo.Parameters[0]);
                    //取Session并发送信息
                    MySessionManager.SessionList[i - 1].Send(requestInfo.Parameters[1]);
                }
            }
        }
    }
}

7.        目录结构:

 

 

8.        MyServer和MySession最终代码:

  a)        MyServer代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SuperSocket.SocketBase;
using SuperSocket.SocketBase.Config;

namespace SuperSocketApp1
{
    /// <summary>
    /// 自定义服务器类MyServer,继承AppServer,并传入自定义连接类MySession
    /// </summary>
    public class MyServer : AppServer<MySession>
    {
        protected override void OnStartup()
        {
            base.OnStartup();
            Console.WriteLine("服务器已启动");
        }

        /// <summary>
        /// 输出新连接信息
        /// </summary>
        /// <param name="session"></param>
        protected override void OnNewSessionConnected(MySession session)
        {
            base.OnNewSessionConnected(session);
            //客户端建立连接,将session加入list
            MySessionManager.SessionList.Add(session);
            Console.Write("
" + session.LocalEndPoint.Address.ToString() + ":连接");
        }

        /// <summary>
        /// 输出断开连接信息
        /// </summary>
        /// <param name="session"></param>
        /// <param name="reason"></param>
        protected override void OnSessionClosed(MySession session, CloseReason reason)
        {
            base.OnSessionClosed(session, reason);
            //客户端断开连接,移除session
            MySessionManager.SessionList.Remove(session);
            Console.Write("
" + session.LocalEndPoint.Address.ToString() + ":断开连接");
        }

        protected override void OnStopped()
        {
            base.OnStopped();
            Console.WriteLine("服务器已停止");
        }
    }
}

  b)        MySession代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SuperSocket;
using SuperSocket.Common;
using SuperSocket.SocketBase;
using SuperSocket.SocketBase.Protocol;

namespace SuperSocketApp1
{
    /// <summary>
    /// 自定义连接类MySession,继承AppSession,并传入到AppSession
    /// </summary>
    public class MySession : AppSession<MySession>
    {
        /// <summary>
        /// 新连接
        /// </summary>
        protected override void OnSessionStarted()
        {
            MySessionManager.SessionList.Add(this);
            Console.WriteLine(this.LocalEndPoint.Address.ToString());
            this.Send("

Hello User");
        }

        /// <summary>
        /// 未知的Command
        /// </summary>
        /// <param name="requestInfo"></param>
        protected override void HandleUnknownRequest(StringRequestInfo requestInfo)
        {
            this.Send("

未知的命令");
        }

        /// <summary>
        /// 捕捉异常并输出
        /// </summary>
        /// <param name="e"></param>
        protected override void HandleException(Exception e)
        {
            this.Send("

异常: {0}", e.Message);
        }

        /// <summary>
        /// 连接关闭
        /// </summary>
        /// <param name="reason"></param>
        protected override void OnSessionClosed(CloseReason reason)
        {
            MySessionManager.SessionList.Remove(this);
            base.OnSessionClosed(reason);
        }
    }
}

9.        注:AppServer类自带方法GetAllSessions()用于获取所有的AppSession:

a)        AppServer中:

foreach (var session in this.GetAllSessions())
            {
                session.Send(now);
            }

  b)        其他地方:

foreach (var session in AppServer.GetAllSessions())
            {
                session.Send(now);
            }


  a)        MyServer代码:
声明:该文观点仅代表作者本人,牛骨文系教育信息发布平台,牛骨文仅提供信息存储空间服务。