Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using c# ClientWebSocket with streams

Tags:

I am currently looking into using websockets to communicate between a client/agent and a server, and decided to look at C# for this purpose. Although I have worked with Websockets before and C# before, this is the first time I using both together. The first attempt used the following guide: 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));
        }
    }
}

Although this seems to work as expected, I was wondering if there is any way I can use the built in streams/readers in .NET with ClientWebSocket?

Seems odd to me that Microsoft has this rich well established set of stream and reader classes, but then decides to implement ClientWebSocket with only the ability to read blocks of bytes that must be handled manually.

Lets say I wanted to transfer xml, it would be easy for me to just wrap the socket stream in a XmlTextReader, but this is not obvious with ClientWebSocket.

like image 608
agnsaft Avatar asked Aug 12 '16 11:08

agnsaft


People also ask

How do I use C on my computer?

It is a bit more cryptic in its style than some other languages, but you get beyond that fairly quickly. C is what is called a compiled language. This means that once you write your C program, you must run it through a C compiler to turn your program into an executable that the computer can run (execute).

What is C language used for?

C programming language is a machine-independent programming language that is mainly used to create many types of applications and operating systems such as Windows, and other complicated programs such as the Oracle database, Git, Python interpreter, and games and is considered a programming foundation in the process of ...

Is C hard to learn?

C is more difficult to learn than JavaScript, but it's a valuable skill to have because most programming languages are actually implemented in C. This is because C is a “machine-level” language. So learning it will teach you how a computer works and will actually make learning new languages in the future easier.


2 Answers

Why don't work with byte arary? What about using 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);
                }
            }
        }
    }
}
like image 58
Artavazd Balayan Avatar answered Sep 21 '22 14:09

Artavazd Balayan


For network operations, someone has to do the work of waiting, checking, reading, waiting, understanding end of message, etc. Your example doesn't really do this, but just waits until 1024 bytes have been read and then stops.

You could implement an abstract Stream class to handle the loop which does the waiting and reading until "finished." Remember that a stream is just an abstraction of a byte-array. Also a Stream does not have the idea of asynchronous reading/writing so you would have to build that if you want it. The key here is that your Stream needs to understand the underlying bytes across the socket so that it knows when reading is finished.

like image 29
matt-dot-net Avatar answered Sep 18 '22 14:09

matt-dot-net