Использование С# ClientWebSocket с потоками
В настоящее время я изучаю использование websockets для связи между клиентом/агентом и сервером и решил посмотреть на С# для этой цели. Хотя я уже работал с Websockets раньше и С#, это первый раз, когда я использую оба вместе. Первая попытка использовала следующее руководство:
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.
Ответы
Ответ 1
Почему бы не работать с байтом arary? Как насчет использования XmlDictionaryReader.CreateTextReader, который принимает массив байтов из сборки System.Runtime.Serialization?. Рабочий код:
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 не имеет идеи асинхронного чтения/записи, поэтому вам нужно будет построить это, если хотите. Ключевым моментом здесь является то, что ваш поток должен понимать базовые байты через сокет, чтобы он знал, когда чтение завершено.