【问题标题】:Using c# ClientWebSocket with streams将 c# ClientWebSocket 与流一起使用
【发布时间】:2016-12-19 09:59:47
【问题描述】:

我目前正在研究使用 websockets 在客户端/代理和服务器之间进行通信,并决定为此使用 C#。虽然我之前使用过 Websockets 和 C#,但这是我第一次同时使用两者。第一次尝试使用以下指南: http://www.codeproject.com/Articles/618032/Using-WebSocket-in-NET-Part

public static void Main(string[] args)
{
    Task t = Echo();
    t.Wait();
}

private static async Task Echo()
{
    using (ClientWebSocket ws = new ClientWebSocket())
    {
        Uri serverUri = new Uri("ws://localhost:49889/");
        await ws.ConnectAsync(serverUri, CancellationToken.None);
        while (ws.State == WebSocketState.Open)
        {
            Console.Write("Input message ('exit' to exit): ");
            string msg = Console.ReadLine();
            if (msg == "exit")
            {
                break;
            }
            ArraySegment<byte> bytesToSend = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msg));
            await ws.SendAsync(bytesToSend, WebSocketMessageType.Text, true, CancellationToken.None);
            ArraySegment<byte> bytesReceived = new ArraySegment<byte>(new byte[1024]);
            WebSocketReceiveResult result = await ws.ReceiveAsync(bytesReceived, CancellationToken.None);
            Console.WriteLine(Encoding.UTF8.GetString(bytesReceived.Array, 0, result.Count));
        }
    }
}

虽然这似乎按预期工作,但我想知道是否有任何方法可以将 .NET 中的内置流/读取器与 ClientWebSocket 一起使用?

我觉得奇怪的是,Microsoft 拥有一套丰富完善的流和读取器类,但随后决定实现 ClientWebSocket,它只能读取必须手动处理的字节块。

假设我想传输 xml,我可以很容易地将套接字流包装在 XmlTextReader 中,但这对于 ClientWebSocket 并不明显。

【问题讨论】:

  • 开始使用 SignalR
  • SignalR 实际上有很多问题。一直很不靠谱。也许我遇到的最大问题是,如果不强制客户端进行更新,就无法升级服务器 SignalR 版本。这并不总是一件好事。

标签: c# websocket


【解决方案1】:

为什么不使用字节数组?使用XmlDictionaryReader.CreateTextReader which accept byte array from System.Runtime.Serialization assembly? 怎么样。 Working code:

namespace XmlReaderOnByteArray
{
    using System;
    using System.Xml;

    class Program
    {
        public static void Main(string[] args)
        {
            // Some XML
            string xml = @"<?xml version=""1.0"" encoding=""UTF-8""?>
                <note>
                <to>Tove</to>
                <from>Jani</from>
                <heading>Reminder</heading>
                <body>Don't forget me this weekend!</body>
                </note>";
            // Get buffer from string
            ArraySegment<byte> arraySegment = new ArraySegment<byte>(System.Text.Encoding.UTF8.GetBytes(xml));
            // Use XmlDictionaryReader.CreateTextReader to create reader on byte array
            using (var reader = XmlDictionaryReader.CreateTextReader(arraySegment.Array, new XmlDictionaryReaderQuotas())) {
                while (reader.Read()) {
                    Console.WriteLine("{0}[{1}] => {2}", reader.Name, reader.NodeType, reader.Value);
                }
            }
        }
    }
}

【讨论】:

【解决方案2】:

对于网络操作,必须有人完成等待、检查、读取、等待、理解消息结束等工作。您的示例并没有真正做到这一点,只是等到读取了 1024 个字节然后停止.

您可以实现一个抽象 Stream 类来处理循环,该循环执行等待和读取直到“完成”。请记住,流只是字节数组的抽象。 Stream 也没有异步读取/写入的想法,因此如果需要,您必须构建它。这里的关键是您的 Stream 需要了解套接字中的底层字节,以便它知道何时完成读取。

【讨论】:

  • 这是否意味着我需要逐块手动读取每个消息(例如读入内存流),直到找到消息的结尾然后处理结果?如果是这样,有一个内置的方法将消息读到最后,而不是猜测接收缓冲区的大小,会不会更方便?
  • 除了你之外,其他人怎么知道消息结束的时间?您正在这里构建协议。
  • 很公平,虽然由于 ClientWebsocket 确实知道消息何时完成,但我希望它提供一些方便的方法来提供完整的消息。我看不出它不应该的原因,因为我认为大多数人可能无论如何都会处理完整的消​​息。
  • 实际上,看起来抽象 Stream API 至少从 .NET 4.5 开始就具有异步读/写方法。
猜你喜欢
  • 1970-01-01
  • 2011-03-22
  • 2011-08-18
  • 2013-08-18
  • 1970-01-01
  • 2019-10-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多