SignalR 设计理念

Posted vbing

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SignalR 设计理念相关的知识,希望对你有一定的参考价值。

SignalR 设计理念(二)

实现客户端和服务器端的实时通讯.

前言:

客户端方法忽略大小写,主要原因基于是URL对大小写不敏感的问题,开发者之间为了更好的协同开发,定下的开发者协议。

问题阐述
  1. 客户端数量不确定!
  2. 同一个用户的客户端数量不确定(一个用户可以多处登陆)!
  3. 客户端连接的渠道不确定(应用程序连接、Web普通连接、WebSocket连接等)!
  4. 同一个用户的连接渠道不一定!

针对以上问题,你会如何设计服务器架构?

SignalR 采用 管道通讯 作为连接消息通道,使用 分配器 对消息适配(基于持久化连接抽象类PersistentConnection实现)。

问:

  1. 管道数如何区分连接渠道? 1

举一反三:

  1. 客户端和服务器之间,消息是如何传递的?

核心代码:

public abstract class PersistentConnection 
{ //持久化连接 【部分代码】

 public virtual Task ProcessRequest(HostContext context)
 {
     if (context == null)
     {
         throw new ArgumentNullException("context");
     }

     if (!_initialized)
     {
         throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Resources.Error_ConnectionNotInitialized));
     }

     if (IsNegotiationRequest(context.Request))
     {
         return ProcessNegotiationRequest(context);
     }
     else if (IsPingRequest(context.Request))
     {
         return ProcessPingRequest(context);
     }

     Transport = GetTransport(context); // 建立运输方式

     if (Transport == null)
     {
         return FailResponse(context.Response, String.Format(CultureInfo.CurrentCulture, Resources.Error_ProtocolErrorUnknownTransport));
     }

     string connectionToken = context.Request.QueryString["connectionToken"];

     if (String.IsNullOrEmpty(connectionToken))
     {
         return FailResponse(context.Response, String.Format(CultureInfo.CurrentCulture, Resources.Error_ProtocolErrorMissingConnectionToken));
     }

     string connectionId;
     string message;
     int statusCode;

     if (!TryGetConnectionId(context, connectionToken, out connectionId, out message, out statusCode))
     {
         return FailResponse(context.Response, message, statusCode);
     }

     Transport.ConnectionId = connectionId;

     // Get the groups token from the request
     return Transport.GetGroupsToken()
                     .Then((g, pc, c) => pc.ProcessRequestPostGroupRead(c, g), this, context)
                     .FastUnwrap();
 }
}

public class TransportManager : ITransportManager
{ //运输机管理器 【部分代码】
 private readonly ConcurrentDictionary<string, Func<HostContext, ITransport>> _transports = new ConcurrentDictionary<string, Func<HostContext, ITransport>>(StringComparer.OrdinalIgnoreCase);
 [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Those are factory methods")]
 public TransportManager(IDependencyResolver resolver)
 {
     if (resolver == null)
     {
         throw new ArgumentNullException("resolver");
     }
     Register("foreverFrame", context => new ForeverFrameTransport(context, resolver));
     Register("serverSentEvents", context => new ServerSentEventsTransport(context, resolver));
     Register("longPolling", context => new LongPollingTransport(context, resolver));
     Register("webSockets", context => new WebSocketTransport(context, resolver));
 }
 // 注册运行机 (可自定义运输方式)
 public void Register(string transportName, Func<HostContext, ITransport> transportFactory)
 {
     if (String.IsNullOrEmpty(transportName))
     {
         throw new ArgumentNullException("transportName");
     }

     if (transportFactory == null)
     {
         throw new ArgumentNullException("transportFactory");
     }

     _transports.TryAdd(transportName, transportFactory);
 }
 // 分配运输机
 public ITransport GetTransport(HostContext hostContext)
 {
     if (hostContext == null)
     {
         throw new ArgumentNullException("hostContext");
     }

     string transportName = hostContext.Request.QueryString["transport"];

     if (String.IsNullOrEmpty(transportName))
     {
         return null;
     }

     Func<HostContext, ITransport> factory;
     if (_transports.TryGetValue(transportName, out factory))
     {
         return factory(hostContext);
     }

     return null;
 }
}
解析:

  1. 由连接中的transport参数区分,有兴趣的朋友可以下载源码深度学习 Microsoft.AspNet.SignalR?

以上是关于SignalR 设计理念的主要内容,如果未能解决你的问题,请参考以下文章

SignalR 设计理念

SignalR OnConnected 与多台服务器和 Redis 背板

使用signalR创建聊天室。

第六节:SignalR完结篇之依赖注入和分布式部署

一步一步学习SignalR进行实时通信_7_非代理

ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室 代码重构使用反射工厂解耦