【问题标题】:SignalR change port - SelfHostSignalR 更改端口 - SelfHost
【发布时间】:2015-05-28 09:34:00
【问题描述】:

我正在尝试使用远程请求更改我的服务器的端口。 当我这样做时,似乎一切正常,但是当我尝试连接时,我得到了一个异常。

如果我关闭(终止进程)然后使用新端口打开(启动进程)服务器,一切正常(客户端设法连接)。

服务器:

internal class Program
{
    private static IDisposable _webApp = null;
    static void Main(string[] args)
    {
        var uri = Start(8089);
        Stop();
        var uri = Start(8089);
        Console.WriteLine("Press enter to exit");
        Console.ReadLine();
    }

    private static string Start(int port)
    {
        var options = new StartOptions();
        var uri = string.Format("http://*:{0}/", port);
        options.Urls.Add(uri);
        options.Settings.Add(typeof(ITraceOutputFactory).FullName, typeof(NullTraceOutputFactory).AssemblyQualifiedName);// disable built-in owin tracing by using a null traceoutput
        var startup = new Startup
            {
                Restart = Restart
            };
        _webApp = WebApp.Start(options, startup.Configuration);
        Trace.Listeners.Remove("HostingTraceListener"); // remove the built-in owin listener
        Console.WriteLine("Server running at " + uri);
        return uri;
    }

    private static void Stop()
    {
        _webApp.Dispose();
    }

    private static string Restart(int port)
    {
        Stop();
        var uri = Start(port);
        return uri;
    }

    internal class NullTraceOutputFactory : ITraceOutputFactory
    {
        public TextWriter Create(string outputFile)
        {
            return StreamWriter.Null;
        }
    }
}

[HubName("Configuration")]
public class ConfigurationHub : Hub
{
    private Func<int, string> _restart;

    public ConfigurationHub(Func<int, string> restart)
    {
        _restart = restart;
    }

    public void ChangePort(int port)
    {
        Console.WriteLine("Port: " + port);
        _restart(port);
    }
}

internal class Startup
{
    public Func<int, string> Restart;

    public void Configuration(IAppBuilder app)
    {
        GlobalHost.DependencyResolver.Register(typeof(ConfigurationHub),
                () => new ConfigurationHub(Restart));
        app.UseCors(CorsOptions.AllowAll);
        //app.UseWelcomePage();
        var hubConfiguration = new HubConfiguration
        {
            EnableJSONP = true,
#if DEBUG
            EnableDetailedErrors = true
#endif
        };

        app.MapSignalR(hubConfiguration);
    }
}

客户:

public partial class Form1 : Form
{
    private IHubProxy _configurationProxy = null;
    private HubConnection _hubConnection;
    private const string CATEGORY = "ABCD";

    public Form1()
    {
        InitializeComponent();
        CreateProxy(8089);
        _hubConnection.Start().Wait();
    }

    private void btnChangePort_Click(object sender, EventArgs e)
    {
        var newPort = Int32.Parse(btnChangePort.Tag as string);
        _configurationProxy.Invoke("ChangePort", newPort);
        _hubConnection.Stop();
        _hubConnection.Dispose();
        _hubConnection = null;
        CreateProxy(newPort);
        _hubConnection.Start().Wait(); // <= Exception when clicking the button
    }

    private void CreateProxy(int newPort)
    {
        //var address = "127.0.0.1";
        var address = "192.168.0.100";
        var port = newPort;
        var config =
            new
                {
                    Name = "Configuration",
                    Pattern = "http://{0}:{1}",
                    Address = address,
                    Port = newPort,
                    QueryString = new Dictionary<string, string> { { "version", "1.0" } },
                    Methods = new[]
                        {
                            "notifyWrongVersion",
#if ERROR
                                "notifyConnected",
#endif
                            //"status",
                            "notifyByeBye"
                        },
                    MethodsCallbacks = new Action[]
                        {
                            () => Console.WriteLine("{0}: You are using the wrong version!", CATEGORY),
#if ERROR
                                    () => Trace.WriteLine("Connected to server! HOORAY!", Categories.CATEGORY_THIS),
#endif
                            () =>
                            Console.WriteLine("{0}: Bye bye from the server. Thank you for discnnecting.", CATEGORY)
                        },
                };

        var url = String.Format(config.Pattern, config.Address, config.Port);

        _hubConnection = new HubConnection(url);
        _hubConnection.TraceLevel = TraceLevels.All;
        _hubConnection.TraceWriter = Console.Out;
        _configurationProxy = _hubConnection.CreateHubProxy(config.Name);
    }
}

例外:

场景:
从客户端和服务器上的端口 8089 开始
按下客户端和服务器上的按钮更改为 8088
关闭客户端
用 8088 端口打开客户端。

客户端日志记录:

14:04:18.2450308 - null - ChangeState(断开连接,连接中) 14:04:18.7762877 - 708038b9-66b0-4cc2-95ac-de45411e453c - WS 连接到: WS://192.168.250.9:8088 / signalr /连接clientProtocol = 1.4&运输=的WebSockets&connectionData = [{ “名称”: “配置”}]&connectionToken = AQAAANCMnd8BFdERjHoAwE%2FCl%2BsBAAAAVaJK6bsSpkyFVlk1Ej463gAAAAACAAAAAAADZgAAwAAAABAAAAAcSxXM3loQOfD31c8mYLdqAAAAAASAAACgAAAAEAAAAISDmfaiIg%2BY%2FVt3bBI%2BZkAoAAAAd%2FngqVkiFGH55BN9NOW4nljYZzHBBwoTLxNwrj%2B31AiShmmgS6euMBQAAADjFYeiwsjjJ% 2BRVX92GYdozAkKthw%3D%3D 14:04:23.8220044 - 708038b9-66b0-4cc2-95ac-de45411e453c - 自动:失败 使用传输 webSockets 连接。系统超时异常: 尝试连接时传输超时 14:04:23.8220044 - 708038b9-66b0-4cc2-95ac-de45411e453c - SSE:获取 http://192.168.250.9:8088/signalr/connect?clientProtocol=1.4&transport=serverSentEvents&connectionData=[ { “名称”: “配置”}]&connectionToken = AQAAANCMnd8BFdERjHoAwE%2FCl%2BsBAAAAVaJK6bsSpkyFVlk1Ej463gAAAAACAAAAAAADZgAAwAAAABAAAAAcSxXM3loQOfD31c8mYLdqAAAAAASAAACgAAAAEAAAAISDmfaiIg%2BY%2FVt3bBI%2BZkAoAAAAd%2FngqVkiFGH55BN9NOW4nljYZzHBBwoTLxNwrj%2B31AiShmmgS6euMBQAAADjFYeiwsjjJ%2BRVX92GYdozAkKthw%3D%3D 14:04:23.9157549 - 708038b9-66b0-4cc2-95ac-de45411e453c - WS: OnClose() 14:04:23.9157549 - 708038b9-66b0-4cc2-95ac-de45411e453c - SSE:OnMessage(数据:初始化)14:04:28.8486354 - 708038b9-66b0-4cc2-95ac-de45411e453c - 自动:无法连接到 使用传输服务器SentEvents。 System.TimeoutException:传输 尝试连接时超时 14:04:28.8642594 - 708038b9-66b0-4cc2-95ac-de45411e453c - LP 连接: http://192.168.250.9:8088/signalr/connect?clientProtocol=1.4&transport=longPolling&connectionData=[ { “名称”: “配置”}]&connectionToken = AQAAANCMnd8BFdERjHoAwE%2FCl%2BsBAAAAVaJK6bsSpkyFVlk1Ej463gAAAAACAAAAAAADZgAAwAAAABAAAAAcSxXM3loQOfD31c8mYLdqAAAAAASAAACgAAAAEAAAAISDmfaiIg%2BY%2FVt3bBI%2BZkAoAAAAd%2FngqVkiFGH55BN9NOW4nljYZzHBBwoTLxNwrj%2B31AiShmmgS6euMBQAAADjFYeiwsjjJ%2BRVX92GYdozAkKthw%3D%3D 14:04:33.8799023 - 708038b9-66b0-4cc2-95ac-de45411e453c - 自动:失败 连接到使用传输长轮询。系统超时异常: 尝试连接时传输超时 14:04:33.8799023 - 708038b9-66b0-4cc2-95ac-de45411e453c - 断开连接 14:04:33.8799023 - 708038b9-66b0-4cc2-95ac-de45411e453c - Transport.Dispose(708038b9-66b0-4cc2-95ac-de45411e453c) 14:04:33.8799023 - 708038b9-66b0-4cc2-95ac-de45411e453c - 关闭

在 3 次出现此错误后,我也得到了这个:

14:14:24.0350106 - null - OnError(System.TimeoutException: 客户端 自 2015 年 5 月 31 日 14:13:27 以来一直处于非活动状态,并且已超过 不活动超时 00:00:50。停止连接。)

【问题讨论】:

  • 请在您的问题中添加异常+堆栈跟踪..
  • 好的。您确定服务器在重新启动后正在运行吗?如果您尝试在浏览器中打开Http://&lt;new server IP and port&gt;/signalr/hubs,它可以工作吗?
  • 是的。它在更改之前和之后都有效。
  • 如果服务器运行并且客户端无法连接(超时),问题必须在客户端吗?您是否尝试在客户端激活SignalR tracing
  • 使用来自客户端的跟踪更新了问题。我认为问题出在服务器端(以进程的打开和关闭查看问题的开头)。

标签: c# client-server signalr port self-hosting


【解决方案1】:

我设法通过以下更改使其工作:

1) 让客户端和服务器在断开连接(客户端)或处置(服务器)之前有时间完成

服务器:

public void ChangePort(int port)
{
    Console.WriteLine("Received ChangePort request: " + port);
    Task.Delay(500).ContinueWith(_ => _restart(port));
}

客户:

_configurationProxy.Invoke("ChangePort", port)
    .ContinueWith(task =>
    {
        if (task.IsFaulted)
        {
            Console.WriteLine("ChangePort faulted: {0}", task.Exception.Flatten()); 
        }

        _hubConnection.Stop();
        _hubConnection.Dispose();
        _hubConnection = null;
    }).Wait();

2) 似乎在服务器处置期间处置了DependencyResolver 并且永远不会返回存在问题(请参阅此GitHub issue)。 This SO question 描述了您遇到的非常相似的问题。这是解决方案:

internal class Startup
    {
        public Func<int, string> Restart;

        public void Configuration(IAppBuilder app)
        {
            var resolver = new DefaultDependencyResolver();
            resolver.Register(typeof(ConfigurationHub), () => new ConfigurationHub(Restart));

            var hubConfiguration = new HubConfiguration
            {
                EnableJSONP = true,
                EnableDetailedErrors = true,
                Resolver = resolver
            };

            app.MapSignalR(hubConfiguration);
        }
    }

【讨论】:

  • 我刚刚尝试了您的代码,但在更改端口并尝试从集线器调用另一个方法后,客户端出现以下异常:无法发送数据,因为连接处于断开状态。在发送任何数据之前调用 start。请在以下链接查看完整项目:bit.do/SignalR
  • 链接中的代码与有问题的代码不同,坦率地说,这是一团糟。我修改了我的解决方案,以便在客户端连接回在新端口上运行的服务器后(重新启动后),它会立即在服务器上调用不同的方法(而不是重新启动)并服务器回调客户端。有用。您可以从here 下载它。我已经为您提供了您无法复制或接受的问题的解决方案,我不愿意与您浪费更多时间......
【解决方案2】:

我们有类似的情况!而不是更改端口,我需要重新启动客户端或服务器端。

我使用计时器和全局标志“已连接”来达到目的。例如如果没有连接则每隔5秒尝试在客户端捕获连接功能,除非没有连接,否则第二次尝试通常可以,因为服务器重启速度不够快,第一次尝试通常失败!

【讨论】:

  • 即使我在端口更改后延迟重新连接,我也会遇到同样的异常
  • 您可以尝试在 btnchange 中移除 createproxy 并开始连接,然后将它们放在另一个按钮中吗?
  • 我可以看到差异,在服务器端你处理 webapp 并重新启动!
  • 为什么处理webapp有问题?
  • 尝试'try catch' createproxy中的所有代码,看看是否有错误信息
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-13
  • 2015-04-02
  • 2015-03-16
  • 1970-01-01
  • 2013-02-13
相关资源
最近更新 更多