当客户端失去连接时,SignalR Owin Linux/Mono Socket上的自主机

Chr*_*Ray 7 c# linux mono socketexception signalr

我在ubuntu服务器14.04,mono 3.2.8上通过Owin运行非常简单的信号服务器.(以下代码).

连接/断开连接在远程Windows服务器和我将位部署到Linux服务器时都能正常工作.但是当客户端意外死亡而不是告诉信号器他正在断开连接时,那就是我只在linux服务器上得到一个永无止境的SocketException.Windows服务器在大约30秒左右后断开客户端,但是linux服务器每隔10秒左右就会发出socketexception(也在下面).

如何在运行相同的代码时使linux服务器像windows服务器一样,在设置超时后断开用户并且不抛出socketexceptions?

服务器代码:

using System;
using System.Threading.Tasks;
using Microsoft.AspNet.SignalR;
using Owin;

namespace signalrtestserver
{
    class Program
    {
        static void Main(string[] args)
        {
            var uri = System.Configuration.ConfigurationManager.AppSettings["startup_uri"] ?? "http://*:7890";
            using (Microsoft.Owin.Hosting.WebApp.Start<Startup>(uri))
            {
                Console.WriteLine(string.Format("Server started on {0}. Press enter to close.", uri));
                Console.ReadLine();
            }
        }
    }

    class Startup
    {
        static Hub hub;

        public void Configuration(IAppBuilder app)
        {
            app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
            var configuration = new HubConfiguration();
            configuration.EnableDetailedErrors = true;
            app.MapSignalR("/signalr", configuration);
            hub = new MyHub();
        }
    }

    public class MyHub : Hub
    {
        public override Task OnConnected() { Console.WriteLine(Context.ConnectionId + " connected"); return base.OnConnected(); }
        public override Task OnDisconnected() { Console.WriteLine(Context.ConnectionId + " disconnected"); return base.OnDisconnected(); }
        public override Task OnReconnected() { Console.WriteLine(Context.ConnectionId + " reconnected"); return base.OnReconnected(); }
    }
}
Run Code Online (Sandbox Code Playgroud)

客户代码:

using System;
using System.Net;
using Microsoft.AspNet.SignalR.Client;

namespace signalrconnection
{
    class Program
    {
        static void Main(string[] args)
        {
            var uri = System.Configuration.ConfigurationManager.AppSettings["signalr_uri"] ?? "http://localhost:7890/signalr";
            ServicePointManager.DefaultConnectionLimit = 10;
            var hubConnection = new HubConnection(uri, false);
            hubConnection.StateChanged += stateChange => Console.WriteLine(string.Format("SignalR {0} >> {1} ({2})", stateChange.OldState, stateChange.NewState, hubConnection.Transport == null ? "<<null>>" : hubConnection.Transport.Name));
            var hubProxy = hubConnection.CreateHubProxy("MyHub");
            hubConnection.Start();
            Console.WriteLine("Press enter to die...");
            Console.ReadLine();
            //hubConnection.Dispose(); //uncomment this to simulate a graceful disconnect which works on both windows and linux
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

永不结束的单声道异常:

{path-to-project}/Microsoft.AspNet.SignalR.Core.dll Error : 0 : SignalR exception thrown by Task: System.AggregateException: One or more errors occured ---> System.IO.IOException: Write failure ---> System.Net.Sockets.SocketException: Connection reset by peer
  at System.Net.Sockets.Socket.Send (System.Byte[] buf, Int32 offset, Int32 size, SocketFlags flags) [0x00000] in <filename unknown>:0
  at System.Net.Sockets.NetworkStream.Write (System.Byte[] buffer, Int32 offset, Int32 size) [0x00000] in <filename unknown>:0
  --- End of inner exception stack trace ---
  at System.Net.Sockets.NetworkStream.Write (System.Byte[] buffer, Int32 offset, Int32 size) [0x00000] in <filename unknown>:0
  at System.Net.ResponseStream.InternalWrite (System.Byte[] buffer, Int32 offset, Int32 count) [0x00000] in <filename unknown>:0
  at System.Net.ResponseStream.Write (System.Byte[] buffer, Int32 offset, Int32 count) [0x00000] in <filename unknown>:0
  at Microsoft.Owin.Host.HttpListener.RequestProcessing.ExceptionFilterStream.Write (System.Byte[] buffer, Int32 offset, Int32 count) [0x00000] in <filename unknown>:0
  --- End of inner exception stack trace ---
 --> (Inner exception 0) System.IO.IOException: Write failure ---> System.Net.Sockets.SocketException: Connection reset by peer
  at System.Net.Sockets.Socket.Send (System.Byte[] buf, Int32 offset, Int32 size, SocketFlags flags) [0x00000] in <filename unknown>:0
  at System.Net.Sockets.NetworkStream.Write (System.Byte[] buffer, Int32 offset, Int32 size) [0x00000] in <filename unknown>:0
  --- End of inner exception stack trace ---
  at System.Net.Sockets.NetworkStream.Write (System.Byte[] buffer, Int32 offset, Int32 size) [0x00000] in <filename unknown>:0
  at System.Net.ResponseStream.InternalWrite (System.Byte[] buffer, Int32 offset, Int32 count) [0x00000] in <filename unknown>:0
  at System.Net.ResponseStream.Write (System.Byte[] buffer, Int32 offset, Int32 count) [0x00000] in <filename unknown>:0
  at Microsoft.Owin.Host.HttpListener.RequestProcessing.ExceptionFilterStream.Write (System.Byte[] buffer, Int32 offset, Int32 count) [0x00000] in <filename unknown>:0
Run Code Online (Sandbox Code Playgroud)

任何帮助将非常感激.提前致谢!

小智 5

问题是这一行static Hub hub,以及hub = new MyHub()你的Startup方法中的这一行.

您不需要显式创建Hub类的实例,也不需要保留引用.每次向服务器发出请求时都会实例化集线器类.请参阅 http://www.asp.net/signalr/overview/signalr-20/hubs-api/hubs-api-guide-server#transience关于Hub对象生存期的部分.


kno*_*cte 3

这意味着每当断开连接时,Linux 中的 Mono 都会抛出与 Windows 中的 MS.NET 不同的异常。SignalR 是由最有可能使用 MS.NET 的人实现的,因此 SignalR 必须预料到某些例外情况并对此保持虔诚。

解决此问题的最佳方法是调试单步执行 SignalR 实现的代码(当在带有 Mono 的 Linux 上运行时),以查看捕获异常的位置,并与 Windows 中 MS.NET 下的 SignalR 中发生的情况进行比较。然后创建一个关于差异的最小测试用例并在http://bugzilla.xamarin.com/中提交一个错误,他们可能会很快修复它(或者你可以将它分配给我,我会看看它,因为我有兴趣在单声道下运行 SignalR)。