>  기사  >  백엔드 개발  >  SignalR Self Host 다중 단말 메시지 푸시 서비스 예시(3)

SignalR Self Host 다중 단말 메시지 푸시 서비스 예시(3)

零下一度
零下一度원래의
2017-07-02 13:19:402151검색

이 글에서는 SignalR Self Host+MVC 등의 멀티 터미널 메시지 푸시 서비스를 주로 소개합니다. 관심 있는 친구들은 참고하시면 됩니다.

1. 프로젝트 요구로 인해 최근에는 회사 프로젝트에서 즉시 승인 알림을 받아야 하는 모듈 기능, 원래 계획은 ajax를 사용하여 서버 쿼리

를 정기적으로 폴링하는 것이었고, 데이터 양과 사용량이 크지 않으면 괜찮았습니다. 처음에는 사용이 증가하고 시스템 내 다양한 ​​비즈니스가 복잡해지면서 서버에 대한 부담도 커지고 있으므로 Ajax 폴링 쿼리를 대체하기 위해 메시지 푸시를 사용하고 싶습니다. 승인 제출 시 push 메소드가 호출되어 메시지를 푸시하므로 서버에 대한 부담이 줄어듭니다.

Signal은 .NET 플랫폼에서 실행되는 Microsoft 지원 HTML 웹소켓 프레임워크입니다. 이 모양의 주요 목적은 서버가 메시지를 클라이언트 페이지에 적극적으로 푸시할 수 있도록 하는 것입니다. 따라서 클라이언트는 메시지를 얻기 위해 요청을 다시 보내거나 폴링 기술을 사용할 필요가 없습니다. 그리고 SignalR의 호환성도 매우 강력하므로 여기서는 자세히 설명하지 않겠습니다. 이제 SignalR을 선택했으므로 시작해 보겠습니다!

내 생각은 SignalR을 자체 호스팅 서비스로 만들고 이를 b/s 프로젝트와 분리하는 것입니다. 이것의 장점은 다음과 같습니다. 1. 푸시 서비스는 iis에 의존하지 않습니다. 2. 이 푸시 서비스를 여러 플랫폼에서 호출할 수 있으며 여러 프로젝트를 동시에 사용할 수 있습니다.

2. 서버 만들기

말도 안 돼요. 블로그를 처음 작성하는 단계, 소개를 마치고 비즈니스 시나리오 및 아이디어, 코딩을 시작하겠습니다.

1. VS를 사용하여 "SignalRProject"라는 솔루션을 만듭니다.

2. SignalRProject 솔루션 아래에 Server라는 새 콘솔을 만듭니다. 3. 패키지 관리자 데스크에서 다음 명령을 입력합니다.

Install-Package Microsoft.AspNet.SignalR.SelfHost

4. 다음 명령을 입력합니다.


Install-Package Microsoft.Owin.Cors

5. 서버 콘솔에 UserInfo 클래스를 추가합니다. 코드는 다음과 같습니다.


using System; 
 
namespace Server 
{ 
 public class UserInfo 
 { 
  public string ConnectionId { get; set; } 
  public string UserName { get; set; } 
  public DateTime LastLoginTime { get; set; } 
 } 
}

6. 서버 콘솔에 ChatHub 클래스를 추가합니다. 코드는 다음과 같습니다


using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.SignalR.Hubs;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Server
{
 [HubName("IMHub")]
 public class ChatHub : Hub
 {
  // 静态属性
  public static List<UserInfo> OnlineUsers = new List<UserInfo>(); // 在线用户列表

  /// <summary>
  /// 登录连线
  /// </summary>
  /// <param name="userId">用户Id</param>
  /// <param name="userName">用户名</param>
  public void Register(string userName)
  {
   var connnectId = Context.ConnectionId;

   if (OnlineUsers.Count(x => x.ConnectionId == connnectId) == 0)
   {
    if (OnlineUsers.Any(x => x.UserName == userName))
    {
     var items = OnlineUsers.Where(x => x.UserName == userName).ToList();
     foreach (var item in items)
     {
      Clients.AllExcept(connnectId).onUserDisconnected(item.ConnectionId, item.UserName);
     }
     OnlineUsers.RemoveAll(x => x.UserName == userName);
    }

    //添加在线人员
    OnlineUsers.Add(new UserInfo
    {
     ConnectionId = connnectId,
     UserName = userName,
     LastLoginTime = DateTime.Now
    });
   }

   // 所有客户端同步在线用户
   Clients.All.onConnected(connnectId, userName, OnlineUsers);
  }

  /// <summary>
  /// 发送私聊
  /// </summary>
  /// <param name="toUserId">接收方用户连接ID</param>
  /// <param name="message">内容</param>
  public void SendPrivateMessage(string toUserName, string message)
  {
   var fromConnectionId = Context.ConnectionId;

   var toUser = OnlineUsers.FirstOrDefault(x => x.UserName == toUserName);
   var fromUser = OnlineUsers.FirstOrDefault(x => x.ConnectionId == fromConnectionId);

   if (toUser != null )
   {
    Clients.Client(toUser.ConnectionId).receivePrivateMessage(fromUser.UserName, message);
    Clients.Client(toUser.ConnectionId).receivePrivateMessage(message);
   }
   else
   {
    //表示对方不在线
    Clients.Caller.absentSubscriber();
   }
  }

  public void Send(string name, string message)
  {
   //Clients.All { get; } // 代表所有客户端
   //Clients.AllExcept(params string[] excludeConnectionIds); // 除了参数中的所有客户端
   //Clients.Client(string connectionId); // 特定的客户端,这个方法也就是我们实现端对端聊天的关键
   //Clients.Clients(IList<string> connectionIds); // 参数中的客户端
   //Clients.Group(string groupName, params string[] excludeConnectionIds); // 指定客户端组,这个也是实现群聊的关键所在
   //Clients.Groups(IList<string> groupNames, params string[] excludeConnectionIds);参数中的客户端组
   //Clients.User(string userId); // 特定的用户
   //Clients.Users(IList<string> userIds); // 参数中的用户

   Console.WriteLine("ConnectionId:{0}, InvokeMethod:{1}", Context.ConnectionId, "Send");
   Clients.All.addMessage(name, message);
  }

  /// <summary>
  /// 连线时调用
  /// </summary>
  /// <returns></returns>
  public override Task OnConnected()
  {
   Console.WriteLine("客户端连接,连接ID是:{0},当前在线人数为{1}", Context.ConnectionId, OnlineUsers.Count+1);
   return base.OnConnected();
  }


  /// <summary>
  /// 断线时调用
  /// </summary>
  /// <param name="stopCalled"></param>
  /// <returns></returns>
  public override Task OnDisconnected(bool stopCalled)
  {
   var user = OnlineUsers.FirstOrDefault(u => u.ConnectionId == Context.ConnectionId);

   // 判断用户是否存在,存在则删除
   if (user == null)
   {
    return base.OnDisconnected(stopCalled);
   }

   Clients.All.onUserDisconnected(user.ConnectionId, user.UserName); //调用客户端用户离线通知
   // 删除用户
   OnlineUsers.Remove(user);
   Console.WriteLine("客户端断线,连接ID是:{0},当前在线人数为{1}", Context.ConnectionId, OnlineUsers.Count);
   return base.OnDisconnected(stopCalled);
  }

  public override Task OnReconnected()
  {
   return base.OnReconnected();
  }
 }
}

7. 서버 콘솔에 Startup 클래스를 추가합니다. 코드는 다음과 같습니다


using Microsoft.Owin.Cors;
using Owin;

namespace Server
{
 public class Startup
 {
  public void Configuration(IAppBuilder app)
  {
   //允许CORS跨域
   app.UseCors(CorsOptions.AllowAll);
   app.MapSignalR();
  }
 }
}

8. 프로그램 클래스를 추가하도록 서버 콘솔을 수정합니다. 코드는 다음과 같습니다


using Microsoft.Owin.Hosting;
using System;

namespace Server
{
 class Program
 {
  static void Main(string[] args)
  {
   string url = "http://localhost:10086";//设定 SignalR Hub Server 对外的接口
   using (WebApp.Start(url))//启动 SignalR Hub Server
   {
    Console.WriteLine("Server running on {0}", url);
    Console.ReadLine();
   }
  }
 }
}

9. F5

를 실행한 다음 http://localhost:10086/signalr/hubs

를 방문합니다.

위 사진 내용을 참고하세요. 오늘은 좀 늦어서 일단 쉬고 글은 정리하겠습니다. 시간이 있어요.

위 내용은 SignalR Self Host 다중 단말 메시지 푸시 서비스 예시(3)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.