Xamarin Mono ClientWebSocket 实现不适用于安全套接字

Posted

技术标签:

【中文标题】Xamarin Mono ClientWebSocket 实现不适用于安全套接字【英文标题】:Xamarin Mono ClientWebSocket implementation doesn't work for secure sockets 【发布时间】:2017-03-11 03:17:57 【问题描述】:

我在 Osx 上实现安全 Web 套接字客户端时遇到问题。 我正在使用 System.Net.WebSockets 中的 ClientWebSocket。下面是一些测试代码:

    static async Task RunLoop()
    
        ClientWebSocket ws = new ClientWebSocket();
        await ws.ConnectAsync(new Uri("wss://echo.websocket.org"), CancellationToken.None);

        do
        
            Console.Write("Enter message:");
            var msg = Console.ReadLine();
            if (msg == "quit")
            
                break;
            

            var b = new ArraySegment<byte>(UTF8Encoding.UTF8.GetBytes(msg));
            await ws.SendAsync(b, WebSocketMessageType.Text, true, CancellationToken.None);

            byte[] bb = new byte[2048];
            ArraySegment<byte> buffer = new ArraySegment<byte>(bb);

            var result = await ws.ReceiveAsync(buffer, CancellationToken.None);

            switch (result.MessageType)
            
                case WebSocketMessageType.Text:
                    Console.WriteLine(UTF8Encoding.UTF8.GetString(buffer.Array));
                    break;
                case WebSocketMessageType.Close:
                    await ws.CloseAsync(WebSocketCloseStatus.NormalClosure, "", CancellationToken.None);
                    break;
            

         while (true);
    

    static void Main(string[] args)
    
        var task = RunLoop();
        task.Wait();
    

每次调用 ReceiveAsync 时我都会收到此异常。

Cannot access a disposed object.

对象名称:'System.Net.Sockets.NetworkStream'。

    at System.Net.WebConnection.Read (System.Net.HttpWebRequest request, System.Byte[] buffer, System.Int32 offset, System.Int32 size) [0x0001f] in /private/tmp/source-mono-4.6.0-c8sr0/bockbuild-mono-4.6.0-branch-c8sr0/profiles/mono-mac-xamarin/build-root/mono-x86/mcs/class/System/System.Net/WebConnection.cs:1038 
  at System.Net.WebSockets.ClientWebSocket+<ReceiveAsync>c__AnonStorey5.<>m__0 () [0x0017c] in /private/tmp/source-mono-4.6.0-c8sr0/bockbuild-mono-4.6.0-branch-c8sr0/profiles/mono-mac-xamarin/build-root/mono-x86/mcs/class/System/System.Net.WebSockets/ClientWebSocket.cs:259 
  at System.Threading.Tasks.Task`1[TResult].InnerInvoke () [0x00012] in /private/tmp/source-mono-4.6.0-c8sr0/bockbuild-mono-4.6.0-branch-c8sr0/profiles/mono-mac-xamarin/build-root/mono-x86/mcs/class/referencesource/mscorlib/system/threading/Tasks/Future.cs:680 
  at System.Threading.Tasks.Task.Execute () [0x00016] in /private/tmp/source-mono-4.6.0-c8sr0/bockbuild-mono-4.6.0-branch-c8sr0/profiles/mono-mac-xamarin/build-root/mono-x86/mcs/class/referencesource/mscorlib/system/threading/Tasks/Task.cs:2502 
--- End of stack trace from previous location where exception was thrown ---
  at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in /private/tmp/source-mono-4.6.0-c8sr0/bockbuild-mono-4.6.0-branch-c8sr0/profiles/mono-mac-xamarin/build-root/mono-x86/mcs/class/referencesource/mscorlib/system/runtime/exceptionservices/exceptionservicescommon.cs:143 
  at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) [0x00047] in /private/tmp/source-mono-4.6.0-c8sr0/bockbuild-mono-4.6.0-branch-c8sr0/profiles/mono-mac-xamarin/build-root/mono-x86/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:187 
  at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) [0x0002e] in /private/tmp/source-mono-4.6.0-c8sr0/bockbuild-mono-4.6.0-branch-c8sr0/profiles/mono-mac-xamarin/build-root/mono-x86/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:156 
  at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) [0x0000b] in /private/tmp/source-mono-4.6.0-c8sr0/bockbuild-mono-4.6.0-branch-c8sr0/profiles/mono-mac-xamarin/build-root/mono-x86/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:128 
  at System.Runtime.CompilerServices.TaskAwaiter`1[TResult].GetResult () [0x00000] in /private/tmp/source-mono-4.6.0-c8sr0/bockbuild-mono-4.6.0-branch-c8sr0/profiles/mono-mac-xamarin/build-root/mono-x86/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:357 
      at Test.MainClass+<RunLoop>c__async2.MoveNext () [0x001c0] in Program.cs:81

看起来套接字以某种方式被丢弃,但我不知道为什么以及在哪里。相同的代码适用于非安全 websocket(“ws://echo.websocket.org”)。

也尝试了 WebSocket.Portable 实现,但遇到了几乎相同的问题。对于非安全 websocket,它运行良好,但对于安全 websocket,OnMessage 事件从未被调用。 https://github.com/NVentimiglia/WebSocket.Portable

【问题讨论】:

相同的代码在 wss 的 windows 上运行良好。 请求后服务器端有警报Frame 9852: 103 bytes on wire (824 bits), 103 bytes captured (824 bits) on interface 0 Ethernet II, Src: Solarfla_07:de:fc (00:0f:53:07:de:fc), Dst: Apple_aa:05:d8 (68:5b:35:aa:05:d8) Internet Protocol Version 4, Src: 54.77.29.155, Dst: 10.40.131.187 Transmission Control Protocol, Src Port: 443, Dst Port: 52146, Seq: 5121, Ack: 1038, Len: 37 Secure Sockets Layer     TLSv1 Record Layer: Encrypted Alert         Content Type: Alert (21)         Version: TLS 1.0 (0x0301)         Length: 32         Alert Message: Encrypted Alert 您找到解决问题的方法了吗?我遇到了类似的问题,我只能使用非安全协议进行连接,而且我不确定为我的 Xamarin 应用程序选择哪种 WebSocket 基础架构。 您好,对此有任何更新 【参考方案1】:

我找到了解决此问题的方法。我使用了 SocketRocker,这是一个 Objective C 实现。 Square.SocketRocket 是本机 Objective C 库的 Xamarin 包装器。 在GitHub 上,您还会在示例目录中找到一些示例。

【讨论】:

以上是关于Xamarin Mono ClientWebSocket 实现不适用于安全套接字的主要内容,如果未能解决你的问题,请参考以下文章

Xamarin - 如何更新 Mono.Android 版本以解决依赖关系?

MAC下 MONO xamarin 怎么不能用 MSBuild

Xamarin Android - 关闭 Mono 日志

mono unity Xamarin 这三者之间是啥关系

Xamarin挖墙脚系列:Xamarin的核心

gles2 动态壁纸转换为 c# (xamarin) 符合错误“...mono.android.TypeManager 无法应用于