【发布时间】: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 谢谢你的建议,它帮助了我!