Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Netzwerke (https://www.delphipraxis.net/14-netzwerke/)
-   -   C# [C#/.NET] Client-Listener möglich? (https://www.delphipraxis.net/150929-%5Bc-net%5D-client-listener-moeglich.html)

Flips 30. Apr 2010 19:23


[C#/.NET] Client-Listener möglich?
 
Hi,

ich hab ein Projekt in C#, das über TCP als Client mit einem Server kommuniziert. Wenn ich dem Server nun beispielsweise ein Kommando sende, dann schickt dieser mir das, was ich mit diesem Kommando anfordere. Quasi das Ping-Pong-Prinzip. Das kann ein riesiger Datensatz sein oder nur die Uhrzeit.
Mit den normalen System.Net.Socket's / TcpClient funktioniert das auch wunderbar, solang bekannt ist, wieviel der Server bei einer bestimmten Anfrage sendet.

Nun gibt es hier ein Problem. Auf ein Request des Clients können auch mal 2-3 Antworten total unterschiedlicher Länge vom Server kommen. Zwischen diesen Antorten kann - der Server ist sehr komplex und hat in Hochzeiten auch viel zu tun - auch durchaus mal eine längere Zeitspanne liegen.


Ich hab es jetzt schon gelöst, nur is die Lösung wirklich sehr quick und verdammt dirty ;-)
Aufbau ist wie folgt (Pseudo):
Code:
TcpClient tcp = new TcpClient();
NetworkStream str = tcp.GetStream();
BinaryReader reader = new BinaryReader(str);
BinaryWriter writer = new BinaryWriter(str);

...
byte[] dummy = new byte[1];
String buffer = "";
do
{
   reader.read(dummy,0,1);
   buffer += B2S(dummy); //B2S = Byte[]ToString, eigene Funktion, funktioniert auch
} while (! buffer.contains(ENDKOMMANDO))
Dabei mache ich mir die Eigenschaft zunutze, dass der Server bei jedem Antworten-Paket ein bestimmtes Kommando am Ende sendet. Quasi ein "das wars, dass sind die Daten zu deinem Request". Ich hab deswegen einfach eine Schleife gemacht die solange "empfängt", bis der empfangene String auch das Abbruchkommando enhält.

Allerdings gibts daher auch 100% Auslastung.
Gibt es nicht irgendeine Möglichkeit quasi ein Client-Listener zu machen, vll ne Callback-Funktion die automatisch horcht ob Daten vom Server kommen?

Danke im Voraus und schönen Feiertag ;-)

TurboMartin 30. Apr 2010 20:33

Re: [C#/.NET] Client-Listener möglich?
 
Du könntest das ganze über die Client-Eigenschaft des TCPClienten lösen. Dabei handelt es sich um das zugrundeliegende Socket, welches auch asynchrones Empfangen von Daten ermöglicht. -> ReciveAsync / BeginReceive

Flips 30. Apr 2010 21:54

Re: [C#/.NET] Client-Listener möglich?
 
Danke dir, die Funktionen hab ich auch schon gesehen. Wusste nur nicht, ob das der richtige Weg ist. Hättest du vielleicht ein etwas angewandteres Beispiel als das des MSDN? Sprache ist dabei ja egal.

TurboMartin 1. Mai 2010 10:52

Re: [C#/.NET] Client-Listener möglich?
 
Code:
    public class AsyncObject
    {
        public bool Connected = false; // ID received flag
        public Socket Socket = null; // Client socket.
        public const int BufferSize = 1024; // Size of receive buffer.
        public byte[] Buffer = new byte[BufferSize];// Receive buffer.
        public List<byte> Received = new List<byte>();
    }
Code:
        protected void ReadCallback(IAsyncResult ar)
        {
            String content = String.Empty;

            AsyncObject state = (AsyncObject)ar.AsyncState;
            Socket handlersocket = state.Socket;
            try
            {
                // Read data from the client socket.
                int bytesRead = handler.EndReceive(ar);

                if (bytesRead > 0)
                {
                    state.Received.AddRange(state.Buffer);
                    content = B2S(state.Buffer);
                    if ((content.Length > 0) && content.Contains(ENDKOMMANDO))
                    {
                        HandleMessages(state, state.Received);
                    }
                    else
                    {
                        // Nicht alle Daten wurden empfangen
                        handlersocket.BeginReceive(state.Buffer, 0, AsyncObject.BufferSize, 0, new AsyncCallback(this.ReadCallback), state);
                    }
                }
                else
                {
                    // Disconnected
                }
            }
            catch (System.Net.Sockets.SocketException es)
            {
                if (es.ErrorCode != 64)
                {
                    Console.WriteLine(string.Format("Socket Exception: {0}, {1}.", es.ErrorCode, es.ToString()));
                }
            }
            catch (Exception e)
            {
                if (e.GetType().FullName != "System.ObjectDisposedException")
                {
                    Console.WriteLine(string.Format("Exception: {0}.", e.ToString()));
                }
            }
        }
Code:
AsyncObject state = new AsyncObject();
state.Socket = tcp.Client;
tcp.Client.BeginReceive(state.Buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(this.ReadCallback), state);

Flips 1. Mai 2010 15:16

Re: [C#/.NET] Client-Listener möglich?
 
Sehr schön, werde den Code mal durcharbeiten und schauen, ob das mein Problem löst!

Mal noch zum Verständnis, synchron bedeutet in dem Fall, dass mein Client eine Anfrage macht und dann solange wartet (blockiert), bis der Server eine Antwort gibt. Es läuft immer nach dem Schema Anfrage - Antwort.
Asynchron bedeutet, der Client sendet eine Anfrage und es muss keine direkte Antwort kommen, das Clientprogramm kann quasi weiterarbeiten (blockiert nicht) und wartet dabei im Hintergrund ständigt auf eventuelle Daten des Servers?

[Edit]
Nach ein wenig zurechtschneiden des Codes funktioniert er super, vielen Dank!!!

Es ist zwar "langsamer" als synchron, aber das ist nicht schlimm. Nur wieso eigentlich?
Also es gibt beispielsweise ein Kommando, wo ich die Antwort weiß. Wenn ich dieses sende und die Antwort synchron wieder emfpange, geht das instantan sofern der Server nicht viel zu tun hat. Bei der asynchronen Lösung braucht er ein paar Sekunden bis er nach gesendetem Kommando in die Callback-Funktion eintritt. Weiß jemand woran das liegt?
[/Edit]

Flips 3. Mai 2010 19:38

Re: [C#/.NET] Client-Listener möglich?
 
OK Nachtrag, nur die erste Antwort des Servers lässt kurz auf sich warten, danach geht es sehr schnell.
Liegt also wohl eher am Server als am Clienten.

Daher ist das die ideale Lösung für das Problem! :thumb:

Tek 26. Nov 2015 10:10

AW: [C#/.NET] Client-Listener möglich?
 
Hi Flips !

ich habe ich selber problem wie du , ich habe schon ein Server , der von Delphi programmiert wurde und versuche ich ein Client mit C# zu programmieren.
Mein Problem ist, dass wenn mein Client die data anfragt, der Server Anwortet nicht.
mein grund idee ist : Der Client soll eine Anfrage senden und soll es Antwort bekommen.

ich bin anfänger bei TCP/ip programmierung. Hiermit möchte ich wissen, ob du noch dein code hast? wenn ja, könntest du mir es zu schicken?

merci d'avance

Tek


Alle Zeitangaben in WEZ +1. Es ist jetzt 17:19 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz