Websocket 信号器AspNetCore无法连接到远程服务器--->;System.Net.WebException

Websocket 信号器AspNetCore无法连接到远程服务器--->;System.Net.WebException,websocket,signalr,azure-service-fabric,stateless,asp.net-core-mvc-2.0,Websocket,Signalr,Azure Service Fabric,Stateless,Asp.net Core Mvc 2.0,我从SignalR客户端应用程序连接到SignalHub时遇到问题,下面给出了错误日志- info: Microsoft.AspNetCore.Sockets.Client.WebSocketsTransport[0] 02/01/2018 15:20:13: Connection Id f763a939-3fb9-4812-ae6e-dfe3198ab37b: Starting transport. Transfer mode: Text. fail: Microsoft.AspN

我从SignalR客户端应用程序连接到SignalHub时遇到问题,下面给出了错误日志-

info: Microsoft.AspNetCore.Sockets.Client.WebSocketsTransport[0]
      02/01/2018 15:20:13: Connection Id f763a939-3fb9-4812-ae6e-dfe3198ab37b: Starting transport. Transfer mode: Text.
fail: Microsoft.AspNetCore.Sockets.Client.HttpConnection[9]02/01/2018 15:20:13: Connection Id f763a939-3fb9-4812-ae6e-dfe3198ab37b: Failed to start connection. Error starting transport 'WebSocketsTransport'.
System.Net.WebSockets.WebSocketException (0x80004005): Unable to connect to the remote server ---> System.Net.WebException: The remote server returned an error: (404) Not Found.
   at System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
   at System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endFunction, Action`1 endAction, Task`1 promise, Boolean requiresSynchronization)
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Net.WebSockets.ClientWebSocket.<ConnectAsyncCore>d__21.MoveNext()
   at System.Net.WebSockets.ClientWebSocket.<ConnectAsyncCore>d__21.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Sockets.Client.WebSocketsTransport.<Connect>d__19.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Sockets.Client.WebSocketsTransport.<StartAsync>d__16.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Sockets.Client.HttpConnection.<StartTransport>d__46.MoveNext()
ChatHub.cs:-

using Microsoft.AspNetCore.SignalR;

namespace SampleChat
{
    public class ChatHub : Hub
    {
        public void Send(string message)
        {
            // Call the broadcastMessage method to update clients.
            Clients.All.InvokeAsync("Send", message);
        }
    }
}
SampleChat.cs

using System.Collections.Generic;
using System.Fabric;
using System.IO;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.ServiceFabric.Services.Communication.AspNetCore;
using Microsoft.ServiceFabric.Services.Communication.Runtime;
using Microsoft.ServiceFabric.Services.Runtime;

namespace SampleChat
{
    /// <summary>
    ///     The FabricRuntime creates an instance of this class for each service type instance.
    /// </summary>
    internal sealed class SampleChat : StatelessService
    {
        public SampleChat(StatelessServiceContext context)
            : base(context)
        {
        }

        /// <summary>
        ///     Optional override to create listeners (like tcp, http) for this service instance.
        /// </summary>
        /// <returns>The collection of listeners.</returns>
        protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
        {
            return new[]
            {
                new ServiceInstanceListener(serviceContext =>
                    new KestrelCommunicationListener(serviceContext, "ServiceEndpoint", (url, listener) =>
                    {
                        ServiceEventSource.Current.ServiceMessage(serviceContext, $"Starting Kestrel on {url}");

                        return new WebHostBuilder()
                            .UseKestrel()
                            .ConfigureServices(
                                services => services
                                    .AddSingleton(serviceContext))
                            .UseContentRoot(Directory.GetCurrentDirectory())
                            .UseStartup<Startup>()
                            .UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.None)
                            .UseUrls(url)
                            .Build();
                    }))
            };
        }
    }
}
SignalRConnector.cs:-

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.SignalR.Client;

namespace SampleChatCoreApplication
{
    static class SignalRConnector
    {
        public static async Task<bool> ConnectoToSignalR()
        {
            var connection = new HubConnectionBuilder()
                .WithUrl("http://localhost:8634/SignalRHub")
                .WithConsoleLogger()
                .WithTransport(Microsoft.AspNetCore.Sockets.TransportType.WebSockets)
                .Build();
            connection.On<string>("Send", data =>
            {
                Console.WriteLine($"Received data: {data}");
            });

            await connection.StartAsync();

            await connection.InvokeAsync("Send", "Send data to Hub");

            Console.ReadKey();

            return true;
        }
    }
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用System.Threading.Tasks;
使用Microsoft.AspNetCore.signal.Client;
命名空间SampleChatCore应用程序
{
静态类信号连接器
{
公共静态异步任务connectotosigner()
{
var connection=new HubConnectionBuilder()
.WithUrl(“http://localhost:8634/SignalRHub")
.WithConsoleLogger()
.WithTransport(Microsoft.AspNetCore.Sockets.TransportType.WebSockets)
.Build();
connection.On(“发送”,数据=>
{
WriteLine($“接收数据:{data}”);
});
等待连接。StartAsync();
等待连接。InvokeAsync(“发送”,“向集线器发送数据”);
Console.ReadKey();
返回true;
}
}
}
当我在本地系统中运行无状态服务时,我能够成功地连接到信号集线器

当服务在azure service fabric群集上运行时,我不知道为什么在连接SignalR client和SignalR hub时会遇到这个问题

有关更多信息,我已查看了网络和 负载平衡器规则,并且没有来自的连接问题 网络端。(我已通过在本文件中添加控制器进行验证 服务,我可以从控制器检索结果)


我做了一些研究和开发,发现这个问题可能和负载平衡器密切相关。为了验证负载平衡器亲和性问题,我使用HTTP协议部署了应用程序,并且我能够在多次重试连接尝试中与其连接。这给了我一个提示,负载平衡器相关性可能会导致这里的问题。 此外,我还检查了应用程序端口的负载平衡器规则,发现负载分布设置为“无”。根据我的理解,应该是“SourceIPProtocol”。 目前,该服务部署在一个5节点的服务结构集群中,当我将服务缩减到1个节点时,我能够在第一次尝试时使用.net framework应用程序通过HTTP和HTTPS协议连接该服务

使用自签名证书部署服务

这里唯一剩下的问题是,我无法通过HTTPS协议从.net标准应用程序连接到该服务,并导致错误-
证书颁发机构无效或不正确

为了从.net framework应用程序进行连接,我在信号器连接代码之前的给定行下面写下了-
ServicePointManager.ServerCertificateValidationCallback+=(o、c、ch、er)=>true

上述给定代码在.net标准应用程序中不起作用

通过进一步的研发,我发现在.NETCore中,
ServicePointManager
HttpClientHandler
实例本身的配置所取代。您需要在IHubConnectionBuilder实例上调用
.WithMessageHandler
,并提供设置了
ServerCertificateCostomValidationCallback
的HttpClientHandler实例

当我使用下面给定的代码时,我无法通过HTTPS协议连接信号集线器-

var handler = new HttpClientHandler
                        {
                            ClientCertificateOptions = ClientCertificateOption.Manual,
                            ServerCertificateCustomValidationCallback = (httpRequestMessage, cert, cetChain, policyErrors) => { return true; }
                        };

                        Connection = new HubConnectionBuilder()
                            .WithUrl(url)
                            .WithTransport(Microsoft.AspNetCore.Sockets.TransportType.WebSockets)
                            .WithMessageHandler(handler)
                            .Build();

当我将传输更改为TransportType.ServerSentEvents或TransportType.LongPolling时,我能够毫无问题地连接到信号集线器。

您确定您的信号器服务器代码的URL正确吗。错误显示该位置为404。由于安全原因,我无法提供运行此应用程序所使用的实际URL。正如我在问题摘要中提到的,使用正确的URL,我能够与使用相同URL托管的MVC控制器通信。因此,这个问题似乎与AspNetCore SignalR库本身有关。您是否尝试导航到您的HubURL/SignalR/Agreement?如果集线器已正确初始化并启动,则应使用json文件进行应答。在我发现的进一步说明中:“对于WebSocket,在Alpha2中,它不支持客户端证书身份验证。但是,在夜间预览1版本中,我们可以使用HubConnectionBuilder上的.WithWebSocketOptions API来配置ClientWebSocketOptions对象,该对象上也有客户端证书配置。”
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.SignalR.Client;

namespace SampleChatCoreApplication
{
    static class SignalRConnector
    {
        public static async Task<bool> ConnectoToSignalR()
        {
            var connection = new HubConnectionBuilder()
                .WithUrl("http://localhost:8634/SignalRHub")
                .WithConsoleLogger()
                .WithTransport(Microsoft.AspNetCore.Sockets.TransportType.WebSockets)
                .Build();
            connection.On<string>("Send", data =>
            {
                Console.WriteLine($"Received data: {data}");
            });

            await connection.StartAsync();

            await connection.InvokeAsync("Send", "Send data to Hub");

            Console.ReadKey();

            return true;
        }
    }
}
var handler = new HttpClientHandler
                        {
                            ClientCertificateOptions = ClientCertificateOption.Manual,
                            ServerCertificateCustomValidationCallback = (httpRequestMessage, cert, cetChain, policyErrors) => { return true; }
                        };

                        Connection = new HubConnectionBuilder()
                            .WithUrl(url)
                            .WithTransport(Microsoft.AspNetCore.Sockets.TransportType.WebSockets)
                            .WithMessageHandler(handler)
                            .Build();