Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Community
  • |
  • Diskussionsforum
Prüfen, ob ein TcpClient noch verbunden ist
idontwantaname
myCSharp.de - Member



Dabei seit:
Beiträge: 87
Herkunft: Österreich

Themenstarter:

Prüfen, ob ein TcpClient noch verbunden ist

beantworten | zitieren | melden

Hallo!

Ich habe folgendes Problem, und zwar schreibe ich eine Server-Anwendung die den TcpListener verwendet und TcpClients entgegennimmt. Das Problem, welches ich hierbei habe ist, dass es mir zur Zeit nicht möglich ist, zu erkennen, ob der Client noch verbunden ist oder nicht.
Habt ihr eine Möglichkeit, wie ich dies prüfen kann?

Schon mal vielen Dank im Vorraus!
Lg oli
private Nachricht | Beiträge des Benutzers
ikaros
myCSharp.de - Member



Dabei seit:
Beiträge: 1787

beantworten | zitieren | melden

Meinst du den Abschied des Gegenüber mittels FIN oder den Bruch der Connection(phys.)?
private Nachricht | Beiträge des Benutzers
idontwantaname
myCSharp.de - Member



Dabei seit:
Beiträge: 87
Herkunft: Österreich

Themenstarter:

beantworten | zitieren | melden

Tut mir Leid, ich weiß leider nicht, was FIN ist, aber eigentlich meine ich wenn der Client die Verbindung trennt, aber dies nicht zuerst über ein Packet ankündigt.
private Nachricht | Beiträge des Benutzers
ikaros
myCSharp.de - Member



Dabei seit:
Beiträge: 1787

beantworten | zitieren | melden

FIN ist ein Signal -> Bedeutung = Bye. Heisst: Vedrbindung angenommen, irgendwas getan(oder nicht) und Verbindung beendet(Socket.Close als Entsprechung). In demFall wird ein FIN gesendet(Benutze Etheral oder einen anderen Packetviewer um es zu sehen). Blöd ist nur das der .Net Client das nicht meldet(zumindest nicht direkt).
Lösung ist das pollen des Readers auf nicht in der MSDN-beschriebenen Weise. Hatte dieses Problem erst vor 3 - 4 Monaten gelöst, muss erst nachschauen.
Es ist feststellbar im Read, weiss nur gerad nicht wie(nachschauen halt, Auswendig hab ich es gerade nicht).
private Nachricht | Beiträge des Benutzers
idontwantaname
myCSharp.de - Member



Dabei seit:
Beiträge: 87
Herkunft: Österreich

Themenstarter:

beantworten | zitieren | melden

Könntest du das vielleicht nachsehen wie das geht?
Weil das wäre echt wichtig für mich!

Vielen Dank jetzt schon mal für deine bisherige und noch zukünftige Mühe
Lg oli
private Nachricht | Beiträge des Benutzers
idontwantaname
myCSharp.de - Member



Dabei seit:
Beiträge: 87
Herkunft: Österreich

Themenstarter:

beantworten | zitieren | melden

Kann mir denn niemand das einm wenig näher erklären?
Ich wäre euch echt sehr dankbar!

Lg oli
private Nachricht | Beiträge des Benutzers
norman_timo
myCSharp.de - Member

Avatar #avatar-1775.jpeg


Dabei seit:
Beiträge: 4591
Herkunft: Wald-Michelbach (Odw)

beantworten | zitieren | melden

Hallo idontwantaname,

ich bin vor Ewigkeiten zu dem Entschluss gekommen, dass es keine zuverlässige Methode gibt, einen TCP/IP Abbruch mitzubekommen. Einzig was hilft ist, dass bei einem "Read" oder bei einem "Write" ein Try-Catch darum zu bauen und im Fehlerfall einen erneuten Verbindungsaufbau zu probieren.

Es gibt auch praktische keine Möglichkeit festzustellen, wenn auf der Gegenseite einfach so jemand das Kabel abzieht. Es gibt hier keine Möglichkeit zu intervenieren oder informiert zu werden. Schon allein deshalb ist Try-Catch eine vernünftige Lösung.

Zusatzinfo:
Ich habe damals auch schon festgestellt, dass MS-Windows2000 zusammen mit Win2003 Server eine "kranke" TCP/IP Verbindung aufbaut, bei der nicht alle gewollten Verbindungsabbrüche gesenset wurden (Known MS-Bug).

Grüße
Norman-Timo
A: “Wie ist denn das Wetter bei euch?”
B: “Caps Lock.”
A: “Hä?”
B: “Na ja, Shift ohne Ende!”
private Nachricht | Beiträge des Benutzers
idontwantaname
myCSharp.de - Member



Dabei seit:
Beiträge: 87
Herkunft: Österreich

Themenstarter:

beantworten | zitieren | melden

Hm, das was du sagst, ist schade :-\
Zur Zeit lese ich so Daten aus, dass eine while-Schleife läuft und wenn der NetworkStream bei DataAvailable true zurückgibt, Daten auslese. Wenn es jedoch zu einem Verbindungabbruch kommt, so wird der Stream wohl immer false bei DataAvailable ausgeben.

Wie kann ich also die Sache angehen, um den Vebindungsabbruch zu erkennen?

Lg oli
private Nachricht | Beiträge des Benutzers
Borg
myCSharp.de - Member



Dabei seit:
Beiträge: 1548
Herkunft: Berlin, Germany

beantworten | zitieren | melden

Einen eigenen TimeOut implementieren.
private Nachricht | Beiträge des Benutzers
ikaros
myCSharp.de - Member



Dabei seit:
Beiträge: 1787

beantworten | zitieren | melden

Zitat
Original von Borg
Einen eigenen TimeOut implementieren.

Ja genau, wenn man weiss wie...
Den Timeout muss man bemerken. Zu meiner Schande - ich hab die Lösung nur immer noch nicht parat.
(Ist aber eigentlich simpel, ...)

_ mea culpa, vertröste auf später...
(trennen ist das derzeitige problem)

Edit: (Stick vergessen)
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von ikaros am .
private Nachricht | Beiträge des Benutzers
idontwantaname
myCSharp.de - Member



Dabei seit:
Beiträge: 87
Herkunft: Österreich

Themenstarter:

beantworten | zitieren | melden

Also ich habe das Problem jetzt selbst gelöst.

Hier die wichtigen Teile:

try
{
  SocketError error;
  int size = client.Receive(buffer, 0, bufferSize, SocketFlags.None, out error);
  if (error == SocketError.Success && size > 0)
  { }
  else
  {
    // Disconnect
  }
}
catch
{
  // Disconnect
}


Hier ist meine Lösung gekapselt in einer Klasse mit Threading und allem drumherum:

using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Threading;

namespace SocketTest
{
    public class TcpServer
    {
        /// <summary>
        /// When a client connects to the server.
        /// </summary>
        public delegate void ClientConnected(Socket client);

        /// <summary>
        /// When a client connects to the server.
        /// </summary>
        public event ClientConnected OnClientConnected;

        /// <summary>
        /// When a client sends data.
        /// </summary>
        public delegate void DataReceived(Socket client, byte[] data);

        /// <summary>
        /// When a client sends data.
        /// </summary>
        public event DataReceived OnDataReceived;

        /// <summary>
        /// When a client disconnects.
        /// </summary>
        public delegate void ClientDisconnected(Socket client);

        /// <summary>
        /// When a client disconnects.
        /// </summary>
        public event ClientDisconnected OnClientDisconnected;

        /// <summary>
        /// The socket on which the tcp server is based on.
        /// </summary>
        private Socket socket;

        /// <summary>
        /// The server's port.
        /// </summary>
        private int port;

        /// <summary>
        /// The buffer size.
        /// </summary>
        private int bufferSize;

        /// <summary>
        /// The thread in which the server listens for incoming connections.
        /// </summary>
        private Thread listeningThread;

        /// <summary>
        /// A list of threads in which interaction with client is handled.
        /// </summary>
        private List<Thread> clientThreads;

        /// <summary>
        /// Defines if the server is active or not.
        /// </summary>
        private bool active;

        /// <summary>
        /// Defines if the server is active or not.
        /// </summary>
        public bool Active
        {
            get
            {
                return active;
            }
        }

        /// <summary>
        /// Creates a new tcp server on a certain port.
        /// </summary>
        /// <param name="port">The port on which the server should run.</param>
        /// <param name="bufferSize">The size of the buffer.</param>
        public TcpServer(int port, int bufferSize)
        {
            this.port = port;
            this.bufferSize = bufferSize;

            clientThreads = new List<Thread>();
        }

        /// <summary>
        /// Starts the server.
        /// <param name="backlog">The max. number of outstanding connections.</param>
        /// </summary>
        public void Start(int backlog)
        {
            active = true;
            try
            {
                IPEndPoint endpoint = new IPEndPoint(new IPAddress(0), port);
                socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                socket.Bind(endpoint);
                socket.Listen(backlog);

                listeningThread = new Thread(new ThreadStart(listen));
                listeningThread.Start();
            }
            catch
            {
                active = false;
            }
        }

        /// <summary>
        /// Stops the server.
        /// </summary>
        public void Stop()
        {
            try
            {
                active = false;
                socket.Close();
            }
            catch { }
        }

        /// <summary>
        /// Method in which the server listens for incoming connections.
        /// </summary>
        private void listen()
        {
            while (active)
            {
                try
                {
                    Socket client = socket.Accept();

                    if (OnClientConnected != null)
                        OnClientConnected(client);

                    Thread thread = new Thread(new ParameterizedThreadStart(work));
                    clientThreads.Add(thread);
                    thread.Start(client);
                }
                catch
                {
                    Stop();
                }
            }
        }

        /// <summary>
        /// Method in which the server communicates with the client.
        /// </summary>
        private void work(object parameter)
        {
            Socket client = (Socket)parameter;

            byte[] buffer = new byte[bufferSize];
            SocketError error = SocketError.Success;

            while (active && client.Connected)
            {
                try
                {
                    int size = client.Receive(buffer, 0, bufferSize, SocketFlags.None, out error);
                    if (error == SocketError.Success && size > 0)
                    {
                        byte[] data = new byte[size];
                        Array.Copy(buffer, data, size);

                        if (OnDataReceived != null)
                            OnDataReceived(client, data);
                    }
                    else
                    {
                        if (OnClientDisconnected != null)
                            OnClientDisconnected(client);

                        client.Shutdown(SocketShutdown.Both);
                        client.Close();
                    }
                }
                catch
                {
                    if (OnClientDisconnected != null)
                        OnClientDisconnected(client);

                    client.Shutdown(SocketShutdown.Both);
                    client.Close();
                }
            }
        }
    }
}
private Nachricht | Beiträge des Benutzers
norman_timo
myCSharp.de - Member

Avatar #avatar-1775.jpeg


Dabei seit:
Beiträge: 4591
Herkunft: Wald-Michelbach (Odw)

beantworten | zitieren | melden

Hallo idontwantaname,

habe den Code nur eben überflogen, und sage, dass das für Deine aktuellen Zwecke wohl ausreicht (sofern Du getestet hast, ob's auch das tut, was es auf den ersten Blick soll :-).

Gruß
Norman-Timo
A: “Wie ist denn das Wetter bei euch?”
B: “Caps Lock.”
A: “Hä?”
B: “Na ja, Shift ohne Ende!”
private Nachricht | Beiträge des Benutzers
idontwantaname
myCSharp.de - Member



Dabei seit:
Beiträge: 87
Herkunft: Österreich

Themenstarter:

beantworten | zitieren | melden

Ja, er tut, was er soll ^^

Aber was meinst du, für meine aktuellen Zwecke sollte er reichen?
Ist er fehlerhaft, unperformant oder hast du Verbesserungsvorschläge?

Lg oli
private Nachricht | Beiträge des Benutzers
norman_timo
myCSharp.de - Member

Avatar #avatar-1775.jpeg


Dabei seit:
Beiträge: 4591
Herkunft: Wald-Michelbach (Odw)

beantworten | zitieren | melden

Hallo idontwantaname,

nein, nein, so ernst ist das nicht ;-)

Ich hätte in meiner Lösung wahrscheinlich noch so etwas wie 3x Reconnect Versuch eingebaut, und auch versucht um das Read den oben genannten Timer einzubauen, denn ein TCP/IP Timeout ist standardmäßig auf 1,5 Minuten eingestellt (WinXP).

Aber das sind alles Ergänzungen, keine Verbesserungsvorschläge und für Deinen Anwendungszweck zunächst Oversize. Ich würde Dir empfehlen Dir dann darüber Gedanken zu machen, wenn es soweit ist. Deine Lösung eignet sich gut für solche Anforderungswechsel, und ist meiner Meinung nach deshalb wirklich gut.

Wie gesagt, habe Deinen Code nur überflogen, nicht analysiert und auch nicht ausprobiert ;-)

Gruß
Norman-Timo
A: “Wie ist denn das Wetter bei euch?”
B: “Caps Lock.”
A: “Hä?”
B: “Na ja, Shift ohne Ende!”
private Nachricht | Beiträge des Benutzers
ikaros
myCSharp.de - Member



Dabei seit:
Beiträge: 1787

beantworten | zitieren | melden

Ich seh gerad nicht die Lösung des geschilderten Problems.
Der gepostete Code ist irgendwie anders(normal).
private Nachricht | Beiträge des Benutzers
idontwantaname
myCSharp.de - Member



Dabei seit:
Beiträge: 87
Herkunft: Österreich

Themenstarter:

beantworten | zitieren | melden

Was meinst du? Ich hab jetzt nicht ganz verstanden, was du zum Ausdruck bringen hast wollen
private Nachricht | Beiträge des Benutzers
ikaros
myCSharp.de - Member



Dabei seit:
Beiträge: 1787

beantworten | zitieren | melden

Es ist ja auch unwichtig, wenn dein Problem damit gelöst ist. Ich unterstellte wohl einfach ein anderes Problem(das ich so Aufgrund der Beschreibung anfangs so annahm) - Dem scheint nicht so.
Ich seh das so: ist dein Problem gelöst, ist alles ok.
Zweifel bei mir kam nur bei Problemen die ich lösen durfte, und ähnlich erschienen(Anfangsbeschreibung)...
private Nachricht | Beiträge des Benutzers
dutchnomad
myCSharp.de - Member



Dabei seit:
Beiträge: 1
Herkunft: Niederlande

beantworten | zitieren | melden

Hallo, Ich habe die genannte code implementiert und getestet. Es scheint zu functionieren, aber wass Ich sehe ist das Folgende:

Mehrere client habe ein Connection mit den Server gemacht, und data is angekommen.
Wann Ich mit netstat /a untersuchte was mit nicht mehr benutzte connection passiert ware sah Ich das sie nicht 'deleted' werden. Wissen Sie wie Ich das Problem kann losen.

Grusse,

Jan, Niederlande
private Nachricht | Beiträge des Benutzers