Laden...

WebSocket Client Beispiel

Erstellt von Olii vor 4 Jahren Letzter Beitrag vor 4 Jahren 9.913 Views
O
Olii Themenstarter:in
76 Beiträge seit 2017
vor 4 Jahren
WebSocket Client Beispiel

Hallo Leute, ich habe mich mal an Sockets versucht, um genauer zu sein mit WebSockets (System.net.Websockets).

Was ich hier versucht habe darzustellen ist eine Klasse die auf der Klasse WebSocketClient aufbaut. Diese Umsetzung sollte mir helfen damit ich sowohl Syncrone als auch Async Clients erstellen kann.

In meinem Anwendungsbeispiel habe ich die Synchrone Art verwendet da ich davon ausgehe in dem Beispiel das der Socket Server auf meine Nachricht wartet, und mir eine Antwort auf meine Nachricht schickt.

Quasi:
Send: Hallo Server, bitte Arbeite folgende Prozedur ab: <DoStuff>
Receive: Hallo Client, die Aufgabe ist erledigt, du kannst dich jetzt trennen

Ich würde gerne ein paar Rückmeldungen haben ob es Dinge gibt die ich verbessern kann oder ob ich grundlegend etwas falsch gemacht habe.

Ich würde gerne etwas daraus lernen 😃

Synchroner Aufruf:


private async void Initialize()
        {
            CustomSocketClient client = new CustomSocketClient("ws://echo.websocket.org/");

            await client.Start();

            await client.Send("Hallo das ist mein Test");

            string message = await client.Receive();
        }

Und hier die Klasse die ich mir dazu gebaut habe:

class CustomSocketClient
    {
        private ClientWebSocket client;

        private string _strAdressEndpoint { get; }
        public string _strNotifyMessage { get; set; }

        public CustomSocketClient(string strAdressEndpoint)
        {
            _strAdressEndpoint = strAdressEndpoint;
            Initialize();
        }

        private void Initialize()
        {
            client = new ClientWebSocket();
            _strNotifyMessage = "notify message";
        }

        public async Task Start()
        {
            await OpenConnection();
        }

        private async Task OpenConnection()
        {
            if(client.State != WebSocketState.Open)
            {
                await client.ConnectAsync(new Uri(_strAdressEndpoint), CancellationToken.None); //ToDo built in CancellationToken
            }
        }

        public async Task<string> Receive()
        {
            byte[] buffer = new byte[1024];
            WebSocketReceiveResult result = await client.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);//ToDo built in CancellationToken

            if (result.MessageType == WebSocketMessageType.Close)
            {
                return "abort";
            }

            using (MemoryStream stream = new MemoryStream())
            {
                stream.Write(buffer,0, result.Count);
                while(!result.EndOfMessage)
                {
                    result = await client.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);//ToDo built in CancellationToken
                    stream.Write(buffer, 0, result.Count);
                }

                stream.Seek(0, SeekOrigin.Begin);
                using (StreamReader reader = new StreamReader(stream, Encoding.UTF8))
                {
                    string message = reader.ReadToEnd();
                    return message;
                }
            }
        }

        public async Task Send(string message)
        {
            if(client.State == WebSocketState.Open)
            {
                byte[] byteContentBuffer = Encoding.UTF8.GetBytes(message);
                await client.SendAsync(new ArraySegment<byte>(byteContentBuffer), WebSocketMessageType.Text, true, CancellationToken.None); //ToDo built in CancellationToken
            }
        }
    }
16.806 Beiträge seit 2008
vor 4 Jahren

Generelles Feedback:

In C# hat man noch nie den Typ der Variable in den Namen gesetzt. Man sieht, dass Du vermutlich von C++ kommst.
_strAdressEndpoint -> _adressEndpoint

Halte Dich auch an die C# Namensempfehlungen (zB Async Suffix bei asynchronen Methoden)
public async Task Start() -> public async Task StartAsync()

Nutze asynchrone Methoden
stream.Write(buffer,0, result.Count); >> stream.WriteAsync(buffer,0, result.Count);

Verwende ConfigureAwait(false)
Use ConfigureAwait

Error Handling über Values oder gar Strings ist ein absolutes No Go

           if (result.MessageType == WebSocketMessageType.Close)
            {
                return "abort";
            }

Weiterhin dürfte Dein Code in der Form nicht (so einfach) testbar sein, weil Du mit der konkreten Implementierung von ClientWebSocket arbeitest.

O
Olii Themenstarter:in
76 Beiträge seit 2017
vor 4 Jahren

Das sind sehr gute Tipps, danke Abt!

Nur eine Frage dazu:

Weiterhin dürfte Dein Code in der Form nicht (so einfach) testbar sein, weil Du mit der konkreten Implementierung von ClientWebSocket arbeitest.

Wie kann ich das verstehen? Dafür gibt es doch den ClientWebSocket oder nich? ^^

Es gibt absolut keine Beispiele im Internet (ich habe Stunden über Stunden nur nach Informationen gesucht, kein Spaß..), weshalb ich dann einfach drauf los gebastelt habe. Auf der MS Seite war als erstes der Client kurz aufgeführt, also hatte ich damit das ganze sofort versucht. War/ist das nicht korrekt?

Irgend eine Idee wo ich was dazu finde? Ein Beispiel oder so? Wie ein WebSocket Server erstellt wird, wird einem an jeder Ecke gezeigt, aber nicht ein kleines Client Beispiel ist zu finden.
Mir fehlt einfach die Idee wie ich es anders machen soll, ich habe gerade absolut keine Vorstellung von einer anderen Sinnvollen umsetzung.

O
Olii Themenstarter:in
76 Beiträge seit 2017
vor 4 Jahren

Zu implementierungen von Clients mit WebSockets konnte ich bisslang leider nicht finden. Allerdings sind wohl 3 Anbieter Librarys wie WebSocket4NET wohl nicht schlecht. Dann werde ich wohl auf diese zurückgreifen und das ganze mal damit probieren.

16.806 Beiträge seit 2008
vor 4 Jahren

In dem anderen Thema von Dir hab ich Dich bereits mehrfach(?) in Richtung SignalR und GRPC geschubst.
Weiß nicht, wieso Du das ignorierst 😉

O
Olii Themenstarter:in
76 Beiträge seit 2017
vor 4 Jahren

Ganz einfach, weil ich absolut keine Ahnung habe wo ich was einsetzten kann. Ich bin überflutet mit Informationen und Möglichkeiten, das ich momentan absolut garnicht mehr weiß was mein eigentliches Problem ist. Kurzgesagt, ich bin absolut überfordert und stehe unter Zeitdruck.

Überall steht irgendetwas das mich immer wieder vermtuten lässt dass das nicht geeignet ist. Z.B .net core signalR.Client, hier steht in der Überschrift:

The ASP.NET Core SignalR .NET client library lets you communicate with SignalR hubs from .NET apps.

Ich habe weder eine asp.net /core Anwendung sonder nur eine .net core Konsolen Anwendung, noch irgendeine Kontroller über den Server, geschweige denn, was dieser überhaupt verwendet. Die Entwickler dieser Server Anwendung sind bereits in Rente und die Software kann erst Ende nächsten Jahres ersetzt werden. Keine Doku oder sonst was. Niemand weiß was das Teil so genau macht, aber alle brauchen es...

16.806 Beiträge seit 2008
vor 4 Jahren

Das sind organisatorische Probleme, die auch Software nicht lösen kann.
Solch eine Organisation führt aber oft auch dazu, dass etwas entwickelt wird, was man kurze Zeit später wegwerfen kann.