SignalR 控制台应用程序示例

Posted

技术标签:

【中文标题】SignalR 控制台应用程序示例【英文标题】:SignalR Console app example 【发布时间】:2012-06-23 19:20:44 【问题描述】:

是否有控制台或 winform 应用程序使用 signalR 向 .net 集线器发送消息的小示例?我已经尝试了 .net 示例并查看了 wiki,但集线器(.net)和客户端(控制台应用程序)之间的关系对我来说没有意义(找不到这样的示例)。应用是否只需要 Hub 的地址和名称即可连接?

如果有人可以提供一小段代码,显示应用程序连接到集线器并发送“Hello World”或 .net 集线器收到的内容?

PS。我有一个运行良好的标准集线器聊天示例,如果我尝试在 Cs 中为其分配集线器名称,它会停止工作,即 [HubName("test")] ,您知道原因吗?。

谢谢。

当前控制台应用代码。

static void Main(string[] args)

    //Set connection
    var connection = new HubConnection("http://localhost:41627/");
    //Make proxy to hub based on hub name on server
    var myHub = connection.CreateProxy("chat");
    //Start connection
    connection.Start().ContinueWith(task =>
    
        if (task.IsFaulted)
        
            Console.WriteLine("There was an error opening the connection:0", task.Exception.GetBaseException());
        
        else
        
            Console.WriteLine("Connected");
        
    ).Wait();

    //connection.StateChanged += connection_StateChanged;

    myHub.Invoke("Send", "HELLO World ").ContinueWith(task => 
        if(task.IsFaulted)
        
            Console.WriteLine("There was an error calling send: 0",task.Exception.GetBaseException());
        
        else
        
            Console.WriteLine("Send Complete.");
        
    );
 

集线器服务器。 (不同的项目工作区)

public class Chat : Hub

    public void Send(string message)
    
        // Call the addMessage method on all clients
        Clients.addMessage(message);
    

信息 Wiki 是 http://www.asp.net/signalr/overview/signalr-20/hubs-api/hubs-api-guide-net-client

【问题讨论】:

好吧,实际上这确实有效,只是以为我得到了相同的结果,只是添加了一些停止点和 Console.ReadLine();在末尾。哇!。 【参考方案1】:

要基于@dyslexicanaboko 对 dotnet 核心的回答,这里有一个客户端控制台应用程序:

创建一个辅助类:

using System;
using Microsoft.AspNetCore.SignalR.Client;

namespace com.***.SignalRClientConsoleApp

    public class SignalRConnection
    
        public async void Start()
        
            var url = "http://signalr-server-url/hubname";

            var connection = new HubConnectionBuilder()
                .WithUrl(url)
                .WithAutomaticReconnect()
                .Build();

            // receive a message from the hub
            connection.On<string, string>("ReceiveMessage", (user, message) => OnReceiveMessage(user, message));

            var t = connection.StartAsync();

            t.Wait();

            // send a message to the hub
            await connection.InvokeAsync("SendMessage", "ConsoleApp", "Message from the console app");
        

        private void OnReceiveMessage(string user, string message)
        
            Console.WriteLine($"user: message");
        

    

然后在你的控制台应用的入口点实现:

using System;

namespace com.***.SignalRClientConsoleApp

    class Program
    
        static void Main(string[] args)
        
            var signalRConnection = new SignalRConnection();
            signalRConnection.Start();

            Console.Read();
        
    

【讨论】:

你的回答对我有很大帮助,但是在现代平台上使用类似 java 的命名空间。 @FedericoBerasategui 大声笑,我一直认为 java 命名空间约定结构良好,并想为什么微软没有采用相同的方式。做了一些阅读,我从未意识到这只是一件旧事。感谢您的提醒。【参考方案2】:

SignalR 2.2.1 示例(2017 年 5 月)

服务器

安装包 Microsoft.AspNet.SignalR.SelfHost -Version 2.2.1

[assembly: OwinStartup(typeof(Program.Startup))]
namespace ConsoleApplication116_SignalRServer

    class Program
    
        static IDisposable SignalR;

        static void Main(string[] args)
        
            string url = "http://127.0.0.1:8088";
            SignalR = WebApp.Start(url);

            Console.ReadKey();
        

        public class Startup
        
            public void Configuration(IAppBuilder app)
            
                app.UseCors(CorsOptions.AllowAll);

                /*  CAMEL CASE & JSON DATE FORMATTING
                 use SignalRContractResolver from
                https://***.com/questions/30005575/signalr-use-camel-case

                var settings = new JsonSerializerSettings()
                
                    DateFormatHandling = DateFormatHandling.IsoDateFormat,
                    DateTimeZoneHandling = DateTimeZoneHandling.Utc
                ;

                settings.ContractResolver = new SignalRContractResolver();
                var serializer = JsonSerializer.Create(settings);
                  
               GlobalHost.DependencyResolver.Register(typeof(JsonSerializer),  () => serializer);                
            
                 */

                app.MapSignalR();
            
        

        [HubName("MyHub")]
        public class MyHub : Hub
        
            public void Send(string name, string message)
            
                Clients.All.addMessage(name, message);
            
        
    

客户

(几乎和Mehrdad Bahrainy的回复一样)

安装包 Microsoft.AspNet.SignalR.Client -Version 2.2.1

namespace ConsoleApplication116_SignalRClient

    class Program
    
        private static void Main(string[] args)
        
            var connection = new HubConnection("http://127.0.0.1:8088/");
            var myHub = connection.CreateHubProxy("MyHub");

            Console.WriteLine("Enter your name");    
            string name = Console.ReadLine();

            connection.Start().ContinueWith(task => 
                if (task.IsFaulted)
                
                    Console.WriteLine("There was an error opening the connection:0", task.Exception.GetBaseException());
                
                else
                
                    Console.WriteLine("Connected");

                    myHub.On<string, string>("addMessage", (s1, s2) => 
                        Console.WriteLine(s1 + ": " + s2);
                    );

                    while (true)
                    
                        Console.WriteLine("Please Enter Message");
                        string message = Console.ReadLine();

                        if (string.IsNullOrEmpty(message))
                        
                            break;
                        

                        myHub.Invoke<string>("Send", name, message).ContinueWith(task1 => 
                            if (task1.IsFaulted)
                            
                                Console.WriteLine("There was an error calling send: 0", task1.Exception.GetBaseException());
                            
                            else
                            
                                Console.WriteLine(task1.Result);
                            
                        );
                    
                

            ).Wait();

            Console.Read();
            connection.Stop();
        
    

【讨论】:

对我不起作用...在 WebApp.Start() 处引发空引用异常 也许你现在如何在这个自托管的信号服务器中全局设置 json 序列化设置(例如 camelCase)? @XarisFytrakis 超级简单,我已经更新了 anwser,你需要从这里获得合约解析器:***.com/questions/30005575/signalr-use-camel-case 以及 DateFormatHandling = DateFormatHandling.IsoDateFormat,如果你从 js 中使用它。 @ADOConnection 感谢您的快速回复。现在的问题是从 .net 客户端调用方法时。例如,如果我在 Hub 类中,调用它: HubContext.Clients.All.UpdateMetric(new Data = "xxx", Something = "yyy", username);我得到具有正确序列化设置(Camel Cased)的 json 响应。但是,如果我使用从客户端(asp.net 客户端)传递的数据来调用它,如下所示: public void UpdateMetric(object metrics, string username) HubContext.Clients.All.UpdateMetric(metrics, username);客户端上的结果不是 Camel Cased。【参考方案3】:

这是针对 dot net core 2.1 - 经过大量试验和错误后,我终于让它完美地工作:

var url = "Hub URL goes here";

var connection = new HubConnectionBuilder()
    .WithUrl($"url")
    .WithAutomaticReconnect() //I don't think this is totally required, but can't hurt either
    .Build();

//Start the connection
var t = connection.StartAsync();

//Wait for the connection to complete
t.Wait();

//Make your call - but in this case don't wait for a response 
//if your goal is to set it and forget it
await connection.InvokeAsync("SendMessage", "User-Server", "Message from the server");

此代码来自您典型的 SignalR 穷人聊天客户端。我和其他许多人似乎遇到的问题是在尝试向集线器发送消息之前建立连接。这很关键,因此等待异步任务完成很重要——这意味着我们通过等待任务完成来使其同步。

【讨论】:

您实际上可以将启动和等待链接为 connection.StartAsync.Wait()【参考方案4】:

首先,您应该通过 nuget 在服务器应用程序上安装 SignalR.Host.Self 并在客户端应用程序上安装 SignalR.Client :

PM> 安装包 SignalR.Hosting.Self -Version 0.5.2

PM> 安装包 Microsoft.AspNet.SignalR.Client

然后将以下代码添加到您的项目中;)

(以管理员身份运行项目)

服务器控制台应用程序:

using System;
using SignalR.Hubs;

namespace SignalR.Hosting.Self.Samples 
    class Program 
        static void Main(string[] args) 
            string url = "http://127.0.0.1:8088/";
            var server = new Server(url);

            // Map the default hub url (/signalr)
            server.MapHubs();

            // Start the server
            server.Start();

            Console.WriteLine("Server running on 0", url);

            // Keep going until somebody hits 'x'
            while (true) 
                ConsoleKeyInfo ki = Console.ReadKey(true);
                if (ki.Key == ConsoleKey.X) 
                    break;
                
            
        

        [HubName("CustomHub")]
        public class MyHub : Hub 
            public string Send(string message) 
                return message;
            

            public void DoSomething(string param) 
                Clients.addMessage(param);
            
        
    

客户端控制台应用程序:

using System;
using SignalR.Client.Hubs;

namespace SignalRConsoleApp 
    internal class Program 
        private static void Main(string[] args) 
            //Set connection
            var connection = new HubConnection("http://127.0.0.1:8088/");
            //Make proxy to hub based on hub name on server
            var myHub = connection.CreateHubProxy("CustomHub");
            //Start connection

            connection.Start().ContinueWith(task => 
                if (task.IsFaulted) 
                    Console.WriteLine("There was an error opening the connection:0",
                                      task.Exception.GetBaseException());
                 else 
                    Console.WriteLine("Connected");
                

            ).Wait();

            myHub.Invoke<string>("Send", "HELLO World ").ContinueWith(task => 
                if (task.IsFaulted) 
                    Console.WriteLine("There was an error calling send: 0",
                                      task.Exception.GetBaseException());
                 else 
                    Console.WriteLine(task.Result);
                
            );

            myHub.On<string>("addMessage", param => 
                Console.WriteLine(param);
            );

            myHub.Invoke<string>("DoSomething", "I'm doing something!!!").Wait();


            Console.Read();
            connection.Stop();
        
    

【讨论】:

你可以在windows应用程序中使用上面的代码但是真的有必要吗?!我不确定你的意思,你可以通过其他方式在windows中通知。 客户端与服务器 0.5.2 到 1.0.0-alpha2 一起工作,例如Install-Package Microsoft.AspNet.SignalR.Client -version 1.0.0-alpha2 nuget.org/packages/Microsoft.AspNet.SignalR.Client/1.0.0-alpha2 (代码和 SignalR 版本应该使用 VS2010 SP1 与 .net 4.0 一起使用)一直试图找出为什么我无法让它工作,最终使用 SignalR 早期版本尝试了客户端。 很好,很有帮助 请注意,您必须在调用connection.Start() 方法之前添加事件侦听器(.On&lt;T&gt;() 方法调用)。 值得提供这个链接:docs.microsoft.com/en-us/aspnet/signalr/overview/…【参考方案5】:

自我宿主现在使用 Owin。结帐http://www.asp.net/signalr/overview/signalr-20/getting-started-with-signalr-20/tutorial-signalr-20-self-host 以设置服务器。它与上面的客户端代码兼容。

【讨论】:

以上是关于SignalR 控制台应用程序示例的主要内容,如果未能解决你的问题,请参考以下文章

SignalR入门之多平台SignalR服务端

从 Mac 中的 ios 客户端调用 PC 中的 signalR 服务器

SignalR的使用

SignalR入门

C# SignalR 异常 - 在收到调用结果之前连接开始重新连接

支持 https 的 Owin 自托管控制台应用程序(无 Web api,无 SignalR)