SignalR 设计理念(二)

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

前言:

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

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

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

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

问:

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

举一反三:

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

核心代码(一):

public abstract class PersistentConnection
{ //持久化连接 【部分代码】
private ITransportManager _transportManager;
public virtual void Initialize(IDependencyResolver resolver)
{
_transportManager = resolver.Resolve<ITransportManager>();
}
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();
}
private ITransport GetTransport(HostContext context)
{
return _transportManager.GetTransport(context);
}
}

核心代码(二):

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 设计理念(二)的更多相关文章

  1. .net mvc 站点自带简易SSL加密传输 Word报告自动生成(例如 导出数据库结构) 微信小程序:动画(Animation) SignalR 设计理念(一) ASP.NET -- WebForm -- ViewState ASP.NET -- 一般处理程序ashx 常用到的一些js方法,记录一下 CryptoJS与C#AES加解密互转

    .net mvc 站点自带简易SSL加密传输   因项目需要,传输数据需要加密,因此有了一些经验,现简易抽出来分享! 请求:前端cryptojs用rsa/aes 或 rsa/des加密,后端.net ...

  2. SignalR 设计理念(一)

    SignalR 设计理念(一) 实现客户端和服务器端的实时通讯. 问题阐述 客户端提供的方法不确定! 客户端的方法参数不确定! 不同的名称和参数要分别调用指定的方法! 调用客户端方法时,忽略大小写! ...

  3. asp.net core 使用 signalR(二)

    asp.net core 使用 signalR(二) Intro 上次介绍了 asp.net core 中使用 signalR 服务端的开发,这次总结一下web前端如何接入和使用 signalR,本文 ...

  4. SignalR入门二、使用 SignalR 2 实现服务器广播

    一.概述 这篇教程通过实现一个股票报价的小程序来讲解如何使用SignalR进行服务器端的推送,服务器会模拟股票价格的波动,并把最新的股票价格推送给所有连接的客户端,最终的运行效果如下图所示. 教程:使 ...

  5. SignalR 教程二 服务端广播

    转帖官方教程:Tutorial: Server Broadcast with SignalR 2 http://www.asp.net/signalr/overview/getting-started ...

  6. 一、SignalR使用心得

    一.通讯模式 以往,我们聊天发消息模式(单体发送消息或通知)-好友(一对一).群组(一对多),方便管理好友-分组方式. 那么聊天和好友管理参考qq,刷新分组标签也页面就会从新加载分组列表和分组内好友列 ...

  7. Angular 初体验

    事情起源当初一个简单的截屏然后推流出去的工具,这个工具当初我用winform简单实现了下,然后因公司业余,添加许多程序包,需要自动管理这些程序包,包含下载更新上传等,以及与后台交互,学生老师提醒,自动 ...

  8. 华为云Stack首席架构师:打造“称手”的数字化工具,答好政企IT数字化转型这道必选题

    摘要:数字化转型是一号位工程,数字化的工具本身就是企业的核心竞争力. 本文分享自华为云社区<华为云Stack首席架构师:打造"称手"的数字化工具,答好政企IT数字化转型这道必 ...

  9. 基于SignalR的消息推送与二维码描登录实现

    1 概要说明 使用微信扫描登录相信大家都不会陌生吧,二维码与手机结合产生了不同应用场景,基于二维码的应用更是比较广泛.为了满足ios.android客户端与web短信平台的结合,特开发了基于Singl ...

随机推荐

  1. hdoj2859(矩阵DP)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2859 思路: 第一次碰到这种矩阵上的DP题,想了半天也没想明白.本来想用子矩阵的左上角坐标和右下角坐标 ...

  2. 取消svn add

    svn commit之前,add的东西都可以取消. 通过先执行svn cleanup,再执行svn revert --recursive example_folder.

  3. Treasures and Vikings(两次搜索)

    Treasures and Vikings https://www.luogu.org/problemnew/show/P4668 题意翻译 你有一张藏宝图,藏宝图可视为 N×MN×M 的网格.每个格 ...

  4. 121. Best Time to Buy and Sell Stock买卖股票12

    一 [抄题]: If you were only permitted to complete at most one transaction (ie, buy one and sell one sha ...

  5. ArrayList与LinkedList的基本添加删除方法 模拟栈 队列

    ArrayList  LinkedList ArrayList的add是在末尾添加 linkedlist也是 offer加在末尾 poll获取并移除此列表的头(第一个元素) peek 获取第一个但不移 ...

  6. 基本控件设置边角图片 drawableleft

    btn.setCompoundDrawablesWithIntrinsicBounds(R.drawable.icon_galley_comment, 0, 0,0); 四个参数分别是左上右下四个方向 ...

  7. php多进程 防止出现僵尸进程

    对于用PHP进行多进程并发编程,不可避免要遇到僵尸进程的问题. 僵尸进程是指的父进程已经退出,而该进程dead之后没有进程接受,就成为僵尸进程(zombie)进程.任何进程在退出前(使用exit退出) ...

  8. Tornado异步阻塞解决方案

    在 tornado 中异步无阻塞的执行耗时任务 在 linux 上 tornado 是基于 epoll 的事件驱动框架,在网络事件上是无阻塞的.但是因为 tornado 自身是单线程的,所以如果我们在 ...

  9. 基于udp的套接字

    1 ss = socket() #创建一个服务器的套接字 2 ss.bind() #绑定服务器套接字 3 inf_loop: #服务器无限循环 4 cs = ss.recvfrom()/ss.send ...

  10. workerman使用

    1.start_timer.php(boc) <?php use \Workerman\Worker; use \Workerman\Lib\Timer; require_once '/var/ ...