SignalR 更改端口 - SelfHost
SignalR change port - SelfHost
我正在尝试使用远程请求更改服务器的端口。
当我这样做时,似乎一切正常,但当我尝试连接时出现异常。
如果我关闭(终止进程)然后打开(启动进程)具有新端口的服务器一切正常(客户端设法连接)。
服务器:
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(Disconnected, Connecting)
14:04:18.7762877 - 708038b9-66b0-4cc2-95ac-de45411e453c - WS
Connecting to:
ws://192.168.250.9:8088/signalr/connect?clientProtocol=1.4&transport=webSockets&connectionData=[{"Name":"Configuration"}]&connectionToken=AQAAANCMnd8BFdERjHoAwE%2FCl%2BsBAAAAVaJK6bsSpkyFVlk1Ej463gAAAAACAAAAAAADZgAAwAAAABAAAAAcSxXM3loQOfD31c8mYLdqAAAAAASAAACgAAAAEAAAAISDmfaiIg%2By%2FVt3bBI%2BZkAoAAAAd%2FngqVkiFGH55BN9NOW4nljYZzHBBwoTLxNwrj%2B31AiShmmgS6euMBQAAADjFYeiwsjjJ%2BRVX92GYdozAkKthw%3D%3D
14:04:23.8220044 - 708038b9-66b0-4cc2-95ac-de45411e453c - Auto: Failed
to connect to using transport webSockets. System.TimeoutException:
Transport timed out trying to connect 14:04:23.8220044 -
708038b9-66b0-4cc2-95ac-de45411e453c - SSE: GET
http://192.168.250.9:8088/signalr/connect?clientProtocol=1.4&transport=serverSentEvents&connectionData=[{"Name":"Configuration"}]&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(Data: initialized) 14:04:28.8486354 -
708038b9-66b0-4cc2-95ac-de45411e453c - Auto: Failed to connect to
using transport serverSentEvents. System.TimeoutException: Transport
timed out trying to connect 14:04:28.8642594 -
708038b9-66b0-4cc2-95ac-de45411e453c - LP Connect:
http://192.168.250.9:8088/signalr/connect?clientProtocol=1.4&transport=longPolling&connectionData=[{"Name":"Configuration"}]&connectionToken=AQAAANCMnd8BFdERjHoAwE%2FCl%2BsBAAAAVaJK6bsSpkyFVlk1Ej463gAAAAACAAAAAAADZgAAwAAAABAAAAAcSxXM3loQOfD31c8mYLdqAAAAAASAAACgAAAAEAAAAISDmfaiIg%2By%2FVt3bBI%2BZkAoAAAAd%2FngqVkiFGH55BN9NOW4nljYZzHBBwoTLxNwrj%2B31AiShmmgS6euMBQAAADjFYeiwsjjJ%2BRVX92GYdozAkKthw%3D%3D
14:04:33.8799023 - 708038b9-66b0-4cc2-95ac-de45411e453c - Auto: Failed
to connect to using transport longPolling. System.TimeoutException:
Transport timed out trying to connect 14:04:33.8799023 -
708038b9-66b0-4cc2-95ac-de45411e453c - Disconnected 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 - Closed
在出现此错误 3 次后,我还得到以下信息:
14:14:24.0350106 - null - OnError(System.TimeoutException: The client
has been inactive since 31/05/2015 14:13:27 and it has exceeded the
inactivity timeout of 00:00:50. Stopping the connection.)
我们有类似的案例!我需要重新启动客户端或服务器端,而不是更改端口。
我使用一个计时器和一个全局标志'is connected'来达到目的。例如如果没有连接,那么每5秒尝试在客户端中捕获连接功能,第二次尝试通常就可以了,除非没有连接,第一次尝试通常会失败,因为服务器重启不够快!
我设法通过以下更改让它工作:
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);
}
}
我正在尝试使用远程请求更改服务器的端口。 当我这样做时,似乎一切正常,但当我尝试连接时出现异常。
如果我关闭(终止进程)然后打开(启动进程)具有新端口的服务器一切正常(客户端设法连接)。
服务器:
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(Disconnected, Connecting) 14:04:18.7762877 - 708038b9-66b0-4cc2-95ac-de45411e453c - WS Connecting to: ws://192.168.250.9:8088/signalr/connect?clientProtocol=1.4&transport=webSockets&connectionData=[{"Name":"Configuration"}]&connectionToken=AQAAANCMnd8BFdERjHoAwE%2FCl%2BsBAAAAVaJK6bsSpkyFVlk1Ej463gAAAAACAAAAAAADZgAAwAAAABAAAAAcSxXM3loQOfD31c8mYLdqAAAAAASAAACgAAAAEAAAAISDmfaiIg%2By%2FVt3bBI%2BZkAoAAAAd%2FngqVkiFGH55BN9NOW4nljYZzHBBwoTLxNwrj%2B31AiShmmgS6euMBQAAADjFYeiwsjjJ%2BRVX92GYdozAkKthw%3D%3D 14:04:23.8220044 - 708038b9-66b0-4cc2-95ac-de45411e453c - Auto: Failed to connect to using transport webSockets. System.TimeoutException: Transport timed out trying to connect 14:04:23.8220044 - 708038b9-66b0-4cc2-95ac-de45411e453c - SSE: GET http://192.168.250.9:8088/signalr/connect?clientProtocol=1.4&transport=serverSentEvents&connectionData=[{"Name":"Configuration"}]&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(Data: initialized) 14:04:28.8486354 - 708038b9-66b0-4cc2-95ac-de45411e453c - Auto: Failed to connect to using transport serverSentEvents. System.TimeoutException: Transport timed out trying to connect 14:04:28.8642594 - 708038b9-66b0-4cc2-95ac-de45411e453c - LP Connect: http://192.168.250.9:8088/signalr/connect?clientProtocol=1.4&transport=longPolling&connectionData=[{"Name":"Configuration"}]&connectionToken=AQAAANCMnd8BFdERjHoAwE%2FCl%2BsBAAAAVaJK6bsSpkyFVlk1Ej463gAAAAACAAAAAAADZgAAwAAAABAAAAAcSxXM3loQOfD31c8mYLdqAAAAAASAAACgAAAAEAAAAISDmfaiIg%2By%2FVt3bBI%2BZkAoAAAAd%2FngqVkiFGH55BN9NOW4nljYZzHBBwoTLxNwrj%2B31AiShmmgS6euMBQAAADjFYeiwsjjJ%2BRVX92GYdozAkKthw%3D%3D 14:04:33.8799023 - 708038b9-66b0-4cc2-95ac-de45411e453c - Auto: Failed to connect to using transport longPolling. System.TimeoutException: Transport timed out trying to connect 14:04:33.8799023 - 708038b9-66b0-4cc2-95ac-de45411e453c - Disconnected 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 - Closed
在出现此错误 3 次后,我还得到以下信息:
14:14:24.0350106 - null - OnError(System.TimeoutException: The client has been inactive since 31/05/2015 14:13:27 and it has exceeded the inactivity timeout of 00:00:50. Stopping the connection.)
我们有类似的案例!我需要重新启动客户端或服务器端,而不是更改端口。
我使用一个计时器和一个全局标志'is connected'来达到目的。例如如果没有连接,那么每5秒尝试在客户端中捕获连接功能,第二次尝试通常就可以了,除非没有连接,第一次尝试通常会失败,因为服务器重启不够快!
我设法通过以下更改让它工作:
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);
}
}