ibcadmin 发表于 2019-9-17 11:34:02

asp.net core 使用 signalR

<h1 id="asp.net-core-利用-signalr一">asp.net core 利用 signalR(一)</h1>
<h2 id="intro">Intro</h2>
<blockquote>
<h2 id="signalr-是什么">SignalR 是什么?</h2>
<p>ASP.NET Core SignalR 是一个开源代码库,它简化了向应用添加实时 Web 功能的过程。 实时 Web 功能使服务器端代码能够即时将内容推送到客户端。</p>
<p>SignalR 的实用对象:</p>
<ul>
<li>必要来自服务器的高频率更新的应用。 比方:游戏、交际网络、投票、拍卖、地图和 GPS 应用。</li>
<li>仪表板和监视应用。 示例包罗公司仪表板、贩卖状态即时更新或行程警示。</li>
<li>协作应用。 协作应用的示例包罗白板应用和团队聚会会议软件。</li>
<li>必要关照的应用。 交际网络、电子邮件、聊天、游戏、行程警示以及许多其他应用都利用关照。</li>
</ul>
<p>SignalR 提供了一个用于创建服务器到客户端远程过程调用(RPC)的 API。 RPC 通过服务器端 .NET Core 代码调用客户端上的 JavaScript 函数。</p>
<p>以下是 ASP.NET Core SignalR 的一些功能:</p>
<ul>
<li><p>自动管理毗连。</p></li>
<li><p>同时向所有毗连的客户端发送消息。 比方,聊天室。</p></li>
<li><p>将消息发送到特定的客户端或客户端组。</p></li>
<li><p>扩展以处置惩罚增长的流量。</p></li>
</ul>
<h2 id="传输">传输</h2>
<p>SignalR 支持几种方法用于处置惩罚实时通讯:</p>
<ul>
<li>WebSockets</li>
<li>服务器发送事故</li>
<li><p>长轮询</p>
<p>SignalR 会从服务器和客户端支持的功能中自动选择最佳传输方法</p></li>
</ul>
</blockquote>
<p>迩来我们在做一个对战的小游戏,类似于之前比较火的答题应用,利用 websocket 来实现客户端和服务器端的通讯,服务器端利用的 <code>SignalR</code></p>
<h2 id="signr-根本利用">SignR 根本利用</h2>
<h3 id="服务注册">服务注册</h3>
<p>服务设置如下:</p>
<code>services.AddSignalR(options =>
    {
      options.HandshakeTimeout = TimeSpan.FromSeconds(3);
      options.KeepAliveInterval = TimeSpan.FromSeconds(10);
    })
    // JSON 序列化设置
    .AddJsonProtocol(options =>
    {
      options.PayloadSerializerSettings.ContractResolver = new DefaultContractResolver();
      options.PayloadSerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Utc;
      options.PayloadSerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
      options.PayloadSerializerSettings.NullValueHandling = NullValueHandling.Ignore;
    });
</code>
<h3 id="认证方式设置">认证方式设置</h3>
<p>默认的 Token 是从哀求头 <code>Authorization</code> 中获取的,而 signalr 哀求服务器端的时候是放在哀求地址的 query string <code>access-token</code> 内里的,以是我们要设置从哀求头中获取大概从 <code>QueryString</code> 里获取,示例设置如下:</p>
<code>services.AddAuthentication(options =>
    {
      options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
      options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
      options.DefaultForbidScheme = JwtBearerDefaults.AuthenticationScheme;
    })
    .AddIdentityServerAuthentication(options =>
    {
      options.Authority = Configuration["Authorization:Authority"];
      options.RequireHttpsMetadata = false;

      options.TokenRetriever = request =>
      {
            var token = TokenRetrieval.FromAuthorizationHeader()(request);
            if (string.IsNullOrWhiteSpace(token))
            {
                token = TokenRetrieval.FromQueryString()(request);
            }

            return token;
      };
    });</code>
<h3 id="configue-设置">Configue 设置</h3>
<code>
app.UseAuthentication();

app.UseSignalR(builder =>
{
    builder.MapHub<QuizGameHub>("/hubs/quizGame"); // 注册 Hub
});

app.UseMvc();</code>
<h3 id="自界说-hub">自界说 Hub</h3>
<h4 id="界说-hub-左券">界说 Hub 左券</h4>
<p>界说一个客户端方法的接口以实现强类型的客户端方法调用,这里客户端调用服务器端的方法也界说了一个接口来束缚,示比方下:</p>
<code>/// <summary>
/// 客户端界说的方法
/// </summary>
public interface IQuizGameClient
{
    Task GameQuestionsReceived(QuizQuestion question);

    Task MatchSuccess(GameInfo gameInfo);

   Task GameAnswerResultReceived(CheckedUserQuizAnswerModel answer);

    Task GameOver(GameResult result);
}

/// <summary>
/// 服务器端界说的方法
/// </summary>
public interface IQuizGameServer
{
    Task<ServiceResult<IReadOnlyList<QuizGameRuleInfo>>> GetGameRules();

    Task AutoMatch(int ruleId);

    Task CheckQuestionAnswer(BaseQuizAnswer model, string gameId);
}</code>
<h4 id="界说-hub">界说 Hub</h4>
<p>有了左券之后,我们就可以界说强类型的 Hub 了,示比方下:</p>
<code>
public partial class QuizGameHub : Hub<IQuizGameClient>, IQuizGameServer
{

    public Task<ServiceResult<IReadOnlyList<QuizGameRuleInfo>>> GetGameRules()
    {
      return Task.FromResult(ServiceResult.Success(QuizGameStorage.GameRuleInfos));
    }
   
    // ...

    public async Task CheckQuestionAnswer(BaseQuizAnswer model, string gameId)
    {
      // 调用客户端方法
      await Clients.User(Context.UserIdentifier)
            .GameAnswerResultReceived(checkedResult); // 向指定用户发送消息
    }
   
    public async Task AutoMatch(int ruleId)
    {
      // ...
    }
}</code>
<h2 id="reference">Reference</h2>
<ul>
<li>https://docs.microsoft.com/en-us/aspnet/core/signalr/introduction?view=aspnetcore-2.2</li>
<li>https://docs.microsoft.com/zh-cn/aspnet/core/signalr/introduction?view=aspnetcore-2.2</li>
</ul><br><br/><br/><br/><br/><br/>来源:<a href="https://www.cnblogs.com/weihanli/archive/2019/09/15/use-signalr-in-aspnetcore.html" target="_blank">https://www.cnblogs.com/weihanli/archive/2019/09/15/use-signalr-in-aspnetcore.html</a>
页: [1]
查看完整版本: asp.net core 使用 signalR