【问题标题】:InternalClientWebSocket instance cannot be used for communication because it has been transitioned into the 'Aborted' stateInternalClientWebSocket 实例无法用于通信,因为它已转换为“已中止”状态
【发布时间】:2018-09-18 14:20:21
【问题描述】:

当我尝试从三个以上的 websocket 接收数据时出现异常。如果我只尝试一个、两个或三个 websocket,它就可以完美运行。 我在这一行得到了例外:

tasks.Add(Send(webSocket, "11"));

异常信息:

异常:System.Net.WebSockets.WebSocketException (0x80004005): 'System.Net.WebSockets.InternalClientWebSocket' 实例不能 用于通信,因为它已被转换为 “中止”状态。 ---> System.OperationCanceledException:操作 取消了。在 System.Threading.CancellationToken.ThrowOperationCanceledException()
在 System.Net.WebSockets.WebSocketConnectionStream.d__21.MoveNext() --- 从先前抛出异常的位置结束堆栈跟踪 --- 在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务 任务)在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务 任务)在 System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(任务任务)
在 System.Net.WebSockets.WebSocketBase.WebSocketOperation.d__19.MoveNext() --- 从先前抛出异常的位置结束堆栈跟踪 --- 在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务 任务)在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务 任务)在 System.Net.WebSockets.WebSocketBase.d__45.MoveNext() 在 System.Net.WebSockets.WebSocketBase.ThrowIfAborted(布尔中止, 异常innerException)在 System.Net.WebSockets.WebSocketBase.ThrowIfConvertibleException(字符串 methodName,Exception异常,CancellationToken cancelToken, 布尔中止)在 System.Net.WebSockets.WebSocketBase.d__45.MoveNext() --- 从先前抛出异常的位置结束堆栈跟踪 --- 在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务 任务)在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务 任务)在 System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() --- 从先前抛出异常的位置结束堆栈跟踪 --- 在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务 任务)在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务 任务)在 System.Runtime.CompilerServices.TaskAwaiter.GetResult()

这是我的代码:

using System;
using System.Collections.Generic;
using System.Net.WebSockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Newtonsoft.Json;
using RTLS_GetData_From_WebSockets.App_Code;

namespace RTLS_GetData_From_WebSockets
{
    class Program
    {
        private static object consoleLock = new object();
        private const int sendChunkSize = 256;
        private const int receiveChunkSize = 256;
        private const bool verbose = true;
        private static readonly TimeSpan delay = TimeSpan.FromMilliseconds(30000);

        private static WebSocket client;
        const string host = "ws://localhost:8080";

        static void Main(string[] args)
        {   
            Connect(host).Wait();
        }

        public static async Task Connect(string uri)
        {
            ClientWebSocket webSocket = null;

            try
            {
                webSocket = new ClientWebSocket();
                await webSocket.ConnectAsync(new Uri(uri), CancellationToken.None);

                List<Task> tasks = new List<Task>();
                tasks.Add(Receive(webSocket));

                tasks.Add(Send(webSocket, "9"));
                tasks.Add(Send(webSocket, "10"));
                tasks.Add(Send(webSocket, "11"));

                await Task.WhenAll(tasks);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Exception: {0}", ex);
            }
            finally
            {
                if (webSocket != null)
                    webSocket.Dispose();
                Console.WriteLine();

                lock (consoleLock)
                {
                    Console.ForegroundColor = ConsoleColor.Red;
                    Console.WriteLine("WebSocket closed.");
                    Console.ResetColor();
                }
            }
        }

        static UTF8Encoding encoder = new UTF8Encoding();

        private static async Task Send(ClientWebSocket webSocket, string ZoneID)
        {
            byte[] buffer = encoder.GetBytes("{\"method\":\"subscribe\", \"resource\":\"/zones/" + ZoneID + "\"}");

            await webSocket.SendAsync(new ArraySegment<byte>(buffer), WebSocketMessageType.Text, true, CancellationToken.None);

            while (webSocket.State == WebSocketState.Open)
            {
                LogStatus(false, buffer, buffer.Length);
                await Task.Delay(delay);
            }
        }

        private static async Task Receive(ClientWebSocket webSocket)
        {
            byte[] buffer = new byte[receiveChunkSize];
            while (webSocket.State == WebSocketState.Open)
            {
                var result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
                if (result.MessageType == WebSocketMessageType.Close)
                {
                    await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None);
                }
                else
                {
                    LogStatus(true, buffer, result.Count);
                }
            }
        }

        private static void LogStatus(bool receiving, byte[] buffer, int length)
        {
            lock (consoleLock)
            {
                Console.ForegroundColor = receiving ? ConsoleColor.Green : ConsoleColor.Gray;

                if (verbose)
                {
                    string tmp = encoder.GetString(buffer);                   
                    var data = JsonConvert.DeserializeObject<Zones>(tmp);
                    Console.WriteLine(data.body.status); 
                    Console.WriteLine();
                }

                Console.ResetColor();
            }
        }
    }
}


    [DataContract]
    public class Zones
    {
        [DataMember(Name = "body")]
        public ZoneBody body { get; set; }
    }

    public class ZoneBody
    {
        [DataMember(Name = "feed_id")]
        public string feed_id { get; set; }

        [DataMember(Name = "zone_id")]
        public string zone_id { get; set; }

        [DataMember(Name = "status")]
        public string status { get; set; }

        [DataMember(Name = "at")]
        public string at { get; set; }
    }

【问题讨论】:

  • ClientWebSocket 不支持并行发送,所以谁知道当您尝试并行发送多条消息时会发生什么。无论如何 - 为什么?一个一个地发送,并行发送对我来说没有任何意义。
  • @Evk 谢谢你的建议,它帮助了我!

标签: c# .net websocket


【解决方案1】:

这是来自 MSDN,这里是 link。

此操作不会阻塞。返回的 Task 对象将完成 ClientWebSocket 实例上的发送请求完成后。

每个 ClientWebSocket 都支持一发一收 并行对象。

一一调用你的 Connect 方法。

【讨论】:

  • 很高兴能帮到你。
猜你喜欢
  • 2012-03-13
  • 2020-09-15
  • 2020-09-15
  • 2018-04-25
  • 2010-10-19
  • 1970-01-01
  • 1970-01-01
  • 2013-08-16
  • 2012-11-02
相关资源
最近更新 更多