Laden...

TCPListener und die Endlosschleife

Erstellt von Der Zaehe vor 18 Jahren Letzter Beitrag vor 18 Jahren 5.054 Views
D
Der Zaehe Themenstarter:in
35 Beiträge seit 2006
vor 18 Jahren
TCPListener und die Endlosschleife

Hallo!

Ich habe angefangen, mir mit Hilfe der MSDN die Verwendung des TcpListener beizubringen und habe nun eine ganz entscheidende Frage: Wie soll ich die Endlosschleife vermeiden, die meine ganze Anwendung blockiert? Ein Vorschlag für die Realisierung eines Multi-Thread-Servers, der mehrere Clients gleichzeitig bearbeiten kann, sieht so aus:


public class ClientHandler 
{

    private TcpClient client;
    private string ID;

    public ClientHandler(TcpClient client, string ID) 
    {

        this.client = client;
        this.ID = ID;
    }

    public void Start() 
    {

        // Den Netzwerk-Stream abrufen.
        NetworkStream stream = client.GetStream();

        // Einen BinaryWriter erstellen, um in den Stream zu schreiben.
        BinaryWriter w = new BinaryWriter(stream);

        // Einen BinaryReader erstellen, um aus dem Stream zu lesen.
        BinaryReader r = new BinaryReader(stream);

        if (r.ReadString() == ClientMessages.RequestConnect) 
        {

            w.Write(ServerMessages.AcknowledgeOK);
            Console.WriteLine(ID + ": Verbindung beendet.");
            while (r.ReadString() != ClientMessages.Disconnect) {}

            Console.WriteLine(ID + ": Verbindungstrennungsanforderung empfangen.");
            w.Write(ServerMessages.Disconnect);
        }
        else 
        {
            Console.WriteLine(ID + ": Verbindung konnte nicht beendet werden.");
        }

        // Den Verbindungs-Socket schließen.
        client.Close();
        Console.WriteLine(ID + ": Verbindung geschlossen.");

        Console.ReadLine();
    }
}

public class TcpServerTest
{
    private static void Main()
    {
        // Erstellen eines neuen Listeners (Abhörer) an Anschluss 8000.
        TcpListener listener = new TcpListener(IPAddress.Parse("127.0.0.1"), 
            8000); 
        
        Console.WriteLine("Server: Initialisiere Anschluss.");
        listener.Start();
        Console.WriteLine("Server: Warte auf eingehende Verbindungsanforderungen...");
        
        int clientNum = 0;
        while (true)
        {
            try 
            {
                // Auf eingehende Verbindungsanforderung warten 
                // und einen für die Kommunikation initalisierten TcpClient zurückgeben. 

                TcpClient client = listener.AcceptTcpClient();
                Console.WriteLine("Server: Verbindung akzeptiert.");

                // Ein neues Objekt erstellen, um diese Verbindung zu bearbeiten.
                clientNum++;
                ClientHandler handler = new ClientHandler(client, "Client " +
                    clientNum.ToString());

                // Dieses Objekt in einem anderen Thread ausführen.
                Thread handlerThread = 
                    new Thread(new ThreadStart(handler.Start));
                handlerThread.IsBackground = true;
                handlerThread.Start();

                // (Sie könnten Handler und HandlerThread auch zu einer Auflistung hinzufügen,
                // um die Client-Sitzungen zu überwachen.)
            }
            catch (Exception err) 
            {
                Console.WriteLine(err.ToString());
            }
        }
    }
}

Da ich den Code leicht verändert in einem Form ausführe, nicht in der Konsole, und das Form noch "bedienbar" sein sollte, müsste ich doch auch noch die Endlosschleife zum Annehmen der Verbindungen in einen speraten Thread tun, oder?

Ich bin von Delphi zu C# "umgesiedelt", da ich gemerkt habe, dass die Sprache einfach viel mehr Möglichkeiten bietet, aber vermisse nun auch die etwas sehr viel leichter zu bedienenden TServerSocket- und TClientSocket-Komponenten, die eine Ebene höher angelegt waren, als es TcpClient und TcpListener sind.

Schon mal Danke für eure Tips! 🙂

mfg
Der Zaehe

B
342 Beiträge seit 2006
vor 18 Jahren

Hi,
warum nimmst du nicht die Methode von Programmierhans:
Multi-TcpClient
Ich hab den Code mal in einer WinForms Anwendung benutzt und alles
hat gefunzt.
Viele Grüße,
Big Al

Da man Spatzen nicht mit Kanonen jagt, sollte man auch nicht mit Computern auf Spatzenhirne losgehen.

D
Der Zaehe Themenstarter:in
35 Beiträge seit 2006
vor 18 Jahren

Danke, genau so etwas habe ich gesucht! =)

Da tut sich noch eine neue Frage auf:
In der Schleife ist ja eine Pause von 100 ms vorgesehen, falls nichts verarbeitet werden muss. Das bedeutet aber auch, das eingehende Daten mit einer maximalen Verzögerung von 100 ms verarbeitet werden. Wie wird dieses Problem in Spielen gelöst, wo bekanntlich ein sehr hoher Ping anzustreben ist?

F
529 Beiträge seit 2003
vor 18 Jahren

Ich habe noch nie ein Spiel programmiert, aber Spiele haben eh immer eine Endlosschleife, in welcher alle Aktionen abgearbeitet werden. Daher ist es auch kein Problem, da auch noch einen Socket abzufragen, ob neue Daten da sind... Und da ein Spiel eigentlich das selbe Verhalten wie eine Endlosschleife hat, welche nirgends pausiert, braucht man auch nirgends das Programm schlafen zu lassen.

Besuchen sie das VisualC++ - Forum

B
342 Beiträge seit 2006
vor 18 Jahren

Da bin ich aber anderer Meinung!
Wenn du dein Programm in einer Endlosschleife laufen lässt
steigt die Prozessoraktivität auf 99%, und das is ja wohl auf
'nem normale PC nicht gut.
Wenn der nur als Server läuft vielleicht, aber sonst???
Big Al
//edit: Hat sich erledigt, hab übersehen, dass du nur von Spielen redest 😁

Da man Spatzen nicht mit Kanonen jagt, sollte man auch nicht mit Computern auf Spatzenhirne losgehen.