一种仿照Asp.net Mvc思惟构建WebSocket服务器的方法

问题场景

Asp.net Mvc提供了DependencyResolver、Routing、Filter、 Modelbinder等webForm所没有新概念,提升Web服务编写的便利性,记得好久以前写的ashx处理程序,因为没有Routing和Modelbinder,代码里写了不少switch case,还有不少参数类型转换,写得满头大汗。如今,开发WebSocket服务端时,一样遇到和ashx差很少的情况:解析数据包,分析Command值,switch(command),而后一个case一个case分支的服务逻辑实现。html

优化思路

若是咱们在webSocket协议之上提出一种请求和回复的数据包的格式约定,正如http在tcp之上的协议约定同样,那么就能够仿照Asp.net Mvc同样,实现服务端的DependencyResolver、Controller、Filter等相似功能,将来业务功能的开发只要继承Controller便可,轻松地实现业务功能代码和基础通信代码彻底分开。固然这个格式约定能够做很简单化,而不是直接复制Http协议,咱们如今约定的格式能够以下:git

{"api":"Login","id":2,"body":["name","password"]}
  • 请求和回复的内容都为Json文本;
  • api指明请求到远程端的哪一个api方法;
  • id为本数据包的惟一标识符;
  • body为请求的远程端api的参数值,为数组;若是是回复,则为回复的对象的json文本 

客户端请求如上的数据到服务器,服务器就自行调用它里面的Login方法,而后将返回值放到请求json的body字段返回给客户端:github

public bool Login(string theName, string thePassword)
{
     return theName == "name" && thePassword == "password";
}

 

 

设计之道

Api服务基础类(FastApiService)的设计

上面的Login方法是一个具体的业务Api,其所在的class派生于FastApiService,FastApiService的职责是反射调用其Login成员方法。web

关于反射性能,能够对Login方法先生成一个调用的委托,缓存起来供下次调用,能够参考asp.net Mvc的ActionMethodDispatcher:http://www.projky.com/asp.netmvc/4.0/System/Web/Mvc/ActionMethodDispatcher.cs.htmljson

FastApiService的职责接口以下:c#

/// <summary>
/// 定义Api服务的执行
/// </summary>
public interface IFastApiService : IDisposable
{
     /// <summary>
     /// 执行Api行为
     /// </summary>              
     /// <param name="actionContext">Api行为上下文</param>      
     void Execute(ActionContext actionContext);
}

 

Routing的设计

这里咱们偷工减料了,不做那么强大,分析请求数据包的api键的字符串值,查找哪一个FastApiService定义了相关的成员方法,从而New出这个FastApiService实例,再调用Execute(ActionContext actionContext);api

 

DependencyResolver的设计

Asp.netMvc+Autofac管理EF的Context对象很是方便,这得利于Asp.netMvc提供了DependencyResolver,能够把Controller的建立给IOC组件来管理,DependencyResolver接口很简单,传入对象类型,返回对象实例,中间过程由IOC来处理。数组

查找哪一个FastApiService定义了相关的成员方法,从而New出这个FastApiService实例缓存

这里获取FastApiService的实例,改成DependencyResolver来获取服务器

 

各部件执行流程

Filter哪里去了

Filter实际是附属的一种东西,在FastApiService的Execute前和后各执行各类Filter就能够了,不论是全局的Filter,仍是打特性的,终究都是Filter,约定好他们的执行顺序就OK!有了Filter,妈妈不再担忧别人还未登陆就请求个人其它Api服务了。

 

 

成果展现

服务器c#代码片段

    /// <summary>
    /// Cpu性能检测控制服务
    /// </summary>   
    public class CpuCounterService : FastApiService
    {
        /// <summary>
        /// 获取版本号
        /// </summary>
        /// <returns></returns>
        [Api]
        [LogFilter("获取版本号")]
        public string GetVersion()
        {
            return this.GetType().Assembly.GetName().Version.ToString();
        }

        /// <summary>
        /// 订阅/取消Cpu变化通知
        /// </summary>       
        /// <returns></returns>
        [Api]
        [LogFilter("订阅/取消Cpu变化通知")]
        public bool SubscribeCpuChangeNotify(bool subscribe)
        {
            this.CurrentContext.Session.TagData.Set("NotifyFlag", subscribe);
            return true;
        }
    }

 

客户端js代码片段

        document.title = '正在链接到服务器 ..';
        var ws = new fastWebSocket('ws://localhost:8282/');

        // 注册api
        ws.bindApi("CpuTimeChanged", function (data) {
            lineChart.addData(data);
        });

        ws.onclose = function (e) {
            document.title = '链接已断开:' + e.code + '' + e.reason;
        };

        ws.onopen = function (e) {
            ws.invkeApi('getVersion', [], function (version) {
                document.title = '服务器版本号:' + version;
            }, function (ex) {
                alert('异常:' + ex);
            });
        };

 

 

栗子下载

https://github.com/xljiulang/NetworkSocket

相关文章
相关标签/搜索