Laden...

Forenbeiträge von BlackBirth Ingesamt 5 Beiträge

25.11.2022 - 14:34 Uhr

Vielen Dank für die Antworten und Verbesserungsvorschlägen, ich werde mich ihrer annehmen und dann mal weiter und weiter an meinen Code arbeiten ... ich denke auch das sehr viel mit der Zeit kommt, jetzt weiß ich aber in welche Richtung/Thema ich mich zuwenden muss.

24.11.2022 - 21:04 Uhr

Ich würds als den Standard Wegwerf/Lern-Spaghetti-Code bezeichnen, den man halt als Anfänger so macht 😉
Aber ist schon besser und mit mehr Verständnis, als viele andere Anfänger so als erstes produzieren. Viele verzweifeln am zB Invoke-Thema etc.

So jetzt meine 3. Version, die funktioniert jetzt eigentlich sehr gut (bei Version 2 war die Clientverwaltung mist). Hab versucht deine Vorschläge umzusetzten. Hab den Code auch komplett allein geschrieben (von Copy und Paste halt nich nicht viel, weil man es besser versteht wenn man es selbs schreibt). Ist denn mein Code jetzt besser geworden? Gibt noch Verbesserungsvorschläge?

Vielen Dank schon mal für die gute Hilfe


using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Collections;

namespace Chat_Server_V3
{
 public partial class Form1 : Form
 {
#region Deklaration
 	TcpListener server;
 	List<serverClient> clientListe = new List<serverClient>();
 	bool isRunning = false;
 	CancellationTokenSource cts = new();
 	Task mainTask;
 	int aktualisieren = 0;
 	bool wdh = false;
#endregion

 	public Form1()
 	{
 		InitializeComponent();
 	}

#region Buttons
 	private async void btn_server_start_Click(object sender, EventArgs e)
 	{
 		CancellationToken token = cts.Token;
 		if (!isRunning)
 		{
 			isRunning = true;
 			lB_chat.Items.Add("Server wird gestartet!");
 			btn_server_start.Text = "Server stoppen";
 			server = new TcpListener(System.Net.IPAddress.Any, 5000);
 			server.Start();
 			 mainTask = Task.Run(() => HandleTcpConnection(token), token);		//Task für das Annehmen von Tcp-Verbindungen
 			await Task.Run(() => lb_client_aktualisieren());
 		}
 		else
 		{
 			btn_server_start.Text = "Server starten";
			isRunning = false;
 			cts.Cancel();

 			await Task.Run(() => server_stoppen());
 		}
 	}

 	private void btn_kick_Click(object sender, EventArgs e)
 	{
 		if (cB_clients.Items.Count != 0 && cB_clients.SelectedIndex >= 0)
 		{
 			int kick = cB_clients.SelectedIndex;
 			clientListe[kick].tcpClient.Close();
 			lB_chat.Items.Add(clientListe[kick].name + " wurde vom Admin gekickt!");
 		}
	}
#endregion


#region Methoden

 	private void HandleTcpConnection(CancellationToken token)		//Auf Verbindung warten und diese annehmen
 	{
 		try
 		{
 			while (!token.IsCancellationRequested)
 			{
 				if (server.Pending())
 				{
 					serverClient newClient = new serverClient();
 					newClient.tcpClient = server.AcceptTcpClient();
 					clientListe.Add(newClient);
 					newClient.ipAdresse = newClient.tcpClient.Client.RemoteEndPoint;
 					Task.Run(() => StreamStarter(newClient));
 					token.ThrowIfCancellationRequested();
 				}
 			}
 		}
 		catch (Exception)
 		{
 			lB_chat.Invoke(new Action(() => lB_chat.Items.Add("Schleife unterbrochen")));
 		}
 	}

 	void StreamStarter(serverClient verbundenerClient)
 	{
 		String sData = null;
 		verbundenerClient.streamWriter = new StreamWriter(verbundenerClient.tcpClient.GetStream(), Encoding.ASCII);
 		verbundenerClient.streamReader = new StreamReader(verbundenerClient.tcpClient.GetStream(), Encoding.ASCII);
 		verbundenerClient.openStream = true;
 		verbundenerClient.name = verbundenerClient.streamReader.ReadLine();
 		lB_chat.Invoke(new Action(() => lB_chat.Items.Add(verbundenerClient.name + " hat sich eingeloggt")));
 		wdh = true;
 		try
 		{
 			while (verbundenerClient.tcpClient.Connected)
 			{
 				sData = verbundenerClient.streamReader.ReadLine();
 				if (sData != null)              //empfangene Daten in Chat ausgeben
 				{
 					lB_chat.Invoke(new Action(() => lB_chat.Items.Add(verbundenerClient.name + ": " + sData)));
 					verbundenerClient.streamWriter.WriteLine("Du hast eine Nachricht erfolgreich gesendet");
 					verbundenerClient.streamWriter.Flush();
 				}
 				if (sData == "ende")            //ausloggen vom Client
 				{
 					lB_chat.Invoke(new Action(() => lB_chat.Items.Add(verbundenerClient.name + " hat sich ausgeloggt!")));
 					verbundenerClient.tcpClient.Close();
 					verbundenerClient.tcpClient.Dispose();
 					verbundenerClient.streamWriter.Close();
 					verbundenerClient.streamWriter.Dispose();
 					verbundenerClient.streamReader.Close();
 					verbundenerClient.streamReader.Dispose();
 					clientListe.Remove(verbundenerClient);
 					break;
 				}
 			}
 		}
 		catch (Exception)  
 		{
 			lB_chat.Invoke(new Action(() => lB_chat.Items.Add("Die Verbindung zu " + verbundenerClient.name + " wurde unterbrochen.")));
 			verbundenerClient.tcpClient.Close();
 			verbundenerClient.tcpClient.Dispose();
 			verbundenerClient.streamWriter.Close();
 			verbundenerClient.streamWriter.Dispose();
 			verbundenerClient.streamReader.Close();
 			verbundenerClient.streamReader.Dispose();
 			clientListe.Remove(verbundenerClient);   
 		}
	}


 	void server_stoppen()
 	{
 		for (int i = 0; i < clientListe.Count; i++)
 		{
 			clientListe[i].tcpClient.Close();
 			clientListe[i].tcpClient.Dispose();
 			clientListe[i].streamWriter.Close();
 			clientListe[i].streamWriter.Dispose();
 			clientListe[i].streamReader.Close();
 			clientListe[i].streamReader.Dispose();
 			clientListe.RemoveAt(i);
 		}

 		cts.Cancel();
 		server.Stop();
 		Thread.Sleep(5);
 		mainTask.Dispose();
 		mainTask = null;
 		cts.Dispose();
 		cts = new CancellationTokenSource();
 		Thread.Sleep(5);
 		lB_clients.Items.Clear();
 		lB_chat.Invoke(new Action(() => lB_chat.Items.Add("Server wurde gestoppt!")));
 	}

 	void lb_client_aktualisieren()
 	{
 		while (isRunning)
 		{
 			if (aktualisieren != clientListe.Count | wdh)
 			{
 				lB_clients.Invoke(new Action(() => lB_clients.Items.Clear()));
 				cB_clients.Invoke(new Action(() => cB_clients.Items.Clear()));
 				try
 				{
 					for (int i = 0; i < clientListe.Count; i++)
 					{
 						cB_clients.Invoke(new Action(() => cB_clients.Items.Add(clientListe[i].name)));
 						lB_clients.Invoke(new Action(() => lB_clients.Items.Add("Name: " + clientListe[i].name)));
 						lB_clients.Invoke(new Action(() => lB_clients.Items.Add("IP-Adresse: " + clientListe[i].ipAdresse.ToString())));
 						lB_clients.Invoke(new Action(() => lB_clients.Items.Add("Stream: " + clientListe[i].openStream.ToString())));
 						lB_clients.Invoke(new Action(() => lB_clients.Items.Add("-----------------")));
 					}
 				}
 				catch (Exception)
 				{
 					lB_clients.Invoke(new Action(() => lB_clients.Items.Clear()));
 					lB_clients.Invoke(new Action(() => lB_clients.Items.Add("Fehler bei der Auflistung")));
 				}
 				aktualisieren = clientListe.Count;
 				wdh = false;
 			}
 		}
 	}

#endregion

#region Klassen

 	public class serverClient
 	{
 		public string name = "";
 		public EndPoint ipAdresse;
 		public TcpClient tcpClient = new TcpClient();
 		public StreamReader streamReader = null;
 		public StreamWriter streamWriter = null;
 		public bool openStream = false;
 	}

#endregion
 }
}


20.11.2022 - 22:13 Uhr

So, hab mal versucht den Code umzuarbeiten. Bis jetzt funktioniert auch alles sehr gut genau so wie ich es will. Kann jetzt meine Clients auch verwalten. Ich wollt fragen ob der Code jetzt besser ist? Ich habe zwar viele Cods gesehen, die das Problem auch lösen, aber die verstehe ich zum großen Teil noch nicht und ich find es besser mich da selbst heranzutasten und nicht einfach coppy und paste zu machen, denn das bringt mich auch im Lernprozess nicht weiter. Mein nächster schritt wird sein die Streams einzubauen und zu verwalten, aber alles nach und nach ;D


using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Collections;

namespace Chat_Server_V1_1
{
    public partial class Form1 : Form
    {
        TcpListener server;
        List<TcpClient> clientListe = new List<TcpClient>();
        Boolean isRunning = true ;
        CancellationTokenSource cts = new();
        Task mainTask;

        public Form1()
        {
            InitializeComponent();
        }

        private async void btn_server_start_Click(object sender, EventArgs e)
        {
            CancellationToken token = cts.Token;
            
            if (isRunning)
            {
                isRunning = false;
                btn_server_start.Text = "Server stoppen";
                server = new TcpListener(System.Net.IPAddress.Any,5000);
                server.Start();               
                mainTask = Task.Run(() => HandleTcpConnection(token),token);
                LBox_Chat.Items.Add("Starte Server");
            }
            else
            {
                
                btn_server_start.Text = "Server starten";
                LBox_Chat.Items.Add("Server wird gstoppt");
                isRunning = true;
                cts.Cancel();

                await Task.Run(() => server_stoppen());
            }
        }

        void HandleTcpConnection(CancellationToken token)
        {         
            LBox_Chat.Invoke(new Action(() => LBox_Chat.Items.Add("Starte Schleife")));
            
            try 
            { 
                while (true)
                {
                    
                    LBox_Chat.Invoke(new Action(() => LBox_Chat.Items.Add("Der Server ist bereit zum verbinden!")));
                    TcpClient neuerCLient  = server.AcceptTcpClient();
                    clientListe.Add(neuerCLient);

                    LBox_Chat.Invoke(new Action(() => LBox_client.Items.Add(neuerCLient.Client.RemoteEndPoint)));

                    token.ThrowIfCancellationRequested();
                }
            }
            catch (Exception)
            {
                LBox_Chat.Invoke(new Action(() => LBox_Chat.Items.Add("Schleife unterbrochen")));
            }
        }

        void server_stoppen()
        {           
            cts.Cancel();
            server.Stop();
            Thread.Sleep(50);
            mainTask.Dispose();
            mainTask = null;                                    
            cts.Dispose();
            cts = new CancellationTokenSource();
            
            LBox_Chat.Invoke(new Action(() => LBox_Chat.Items.Add("Server wurde gestoppt")));
        }

        private void btn_clients_show_Click(object sender, EventArgs e) 
        {
            LBox_client.Items.Clear();
            for (int i = 0; i < clientListe.Count; i++)
            { 
                LBox_client.Items.Add(clientListe[i].Client.RemoteEndPoint);
            } 
        }

        private void button1_Click(object sender, EventArgs e)   // für null dann den Index angeben der gekickt werden soll 
        {
            clientListe[0].Close();
            clientListe[0].Dispose();
            clientListe.RemoveAt(0);
        }
    }
}

16.11.2022 - 17:24 Uhr

Danke Abt an die ausführliche Hilfe, ich versuch es mal umzuarbeiten / neu aufzubauen.
Da ist keine Lernaufgabe, sondern will ich einfach nur Lernen zu programmieren, vielleicht mal das ein oder andre Tool schreiben oder vielleicht auch mal nen kleines Kartenspiel oder so. Da will ich mich halt langsam herantasten und hab gedacht, dass das Chatprogram eine gute Übung ist um mit Daten übers Netzwerk zu schicken und diese zu verarbeiten. Auch der Umgang mit TCP-Server/Client wollte ich damit erkunden. Das meine ersten Programme nicht so perfekt sind ist mir klar, aber ich hoffe das wird sich bessern.
Vielen Dank

15.11.2022 - 22:21 Uhr

Hallo, ich bin Anfänger im Programmieren. Habe schon ein paar Programme geschrieben und versuche mich mit Hilfe eines Chat-Programmes an der Netzwergprogrammierung und dem Threading. Anfangs habe ich nur eine Nachricht per TcpClient und TcpListener verschickt und das ging auch soweit und möchte das jetzt erweitern.
Es soll einen zentralen Server geben der alle eingehenden Verbindungen annimmt und die Texte in einer Listbox anzeigt. Bei der Annahme soll in einer 2. Box die IP-Adresse angezeigt werden und anschließend auch der einloggende Name später dann auch. In der ComboBox sollen dann die IPs angezeigt und auswählbar sein. Soweit funktioniert das auch.
Der Client loggt sich per Console ein sendet per Stream erst seinen Namen dann den Text und empfängt auch eine Bestätigung der Sendung.
Noch nicht implementiert, dass alle auch alle Nachrichten sehen und das der Server Nachrichten senden kann, da ich erst die anderen Probleme lösen möchte.

Problem 1:
Mit dem Kick-Button soll die Verbindung mit ausgewählten IP-Adresse in der Combobox getrennt werden. Ich weiß nicht wie ich die beenden kann.

Problem 2:
Ich kann den Server nicht beenden, da die while-Schleife in HandleConnection() mit dem interrupt des Threads nicht beendet wird und immer ein Fehler wirft, da AcceptTcpClient() wahrscheinlich noch auf Verbindungen wartet und wenn der Server gestoppt wird den Fehler erzeugt.

Frage 1: Der Thread t läuft ja in einer Schleife und erzeugt pro eingehende Verbindung einen neuen Thread tc. Wie kann ich die Threads auflisten oder unterscheiden bzw. darauf zugreifen? Später soll eine maximale Anzahl an Verbindungen eingebaut werden und Dopplungen von IPs vermieden werden.

Frage 2: Ist die Prozessstruktur so einigermaßen in Ordnung? Oder sollte ich sie grundsätzlich ändern?

Vielen Dank schon mal im Voraus, und bitte seid nachsichtig ich bin blutiger Anfänger!


using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Chat_Server
{
    public partial class Form1 : Form
    {
        private TcpListener server;
        private Boolean isRunnig = false;
        private Thread t;

        public Form1()
        {
            InitializeComponent();
        }

        public void btn_server_start_Click(object sender, EventArgs e)
        {
            isRunnig = true;
            t = new Thread(HandleConnection);                        
            t.Start();
            LBox_chat.Items.Add("Server gestartet!");
            
            Thread aktualisieren = new Thread(cBox_aktualisieren);
            aktualisieren.Start();
        }

        private void btn_server_close_Click(object sender, EventArgs e)
        {
            isRunnig = false;
            t.Interrupt();
            server.Stop();
            LBox_chat.Items.Add("Server gestoppt!");
            
        }

        private void btn_send_Click(object sender, EventArgs e)
        {
            tBox_eingabe.Text = "";
        }

        private void btn_client_kick_Click(object sender, EventArgs e)
        {
            LBox_chat.Items.Add(" wurde vom Server gekickt!");
        }

        private void HandleConnection()                                                 //Zuweisungen der Ankommenden Verbindungen
        {
            server = new TcpListener(System.Net.IPAddress.Any, 5732);                                         
            server.Start();

                while (isRunnig)
                {
                    TcpClient newClient = server.AcceptTcpClient();                     
                    Thread tc = new Thread(new ParameterizedThreadStart(HandleClient));  
                    tc.Start(newClient);                                                 

                    LBox_clients.Invoke(new Action(() => LBox_clients.Items.Add(newClient.Client.RemoteEndPoint.ToString())));
                }

        }

        public void HandleClient(object obj)                  //Methode der einselnen Clients zum lesen und schreiben
        {
            String name;

            TcpClient client = (TcpClient)obj;
            StreamWriter writer = new StreamWriter(client.GetStream(), Encoding.ASCII);
            StreamReader reader = new StreamReader(client.GetStream(), Encoding.ASCII);

            Boolean bClieantConnectet = true;
            String sData = null;
            name = reader.ReadLine();

            LBox_chat.Invoke(new Action(() => LBox_chat.Items.Add(name + " hat sich eingeloggt")));
            LBox_clients.Invoke(new Action(() => LBox_clients.Items.Remove(client.Client.RemoteEndPoint.ToString())));
            LBox_clients.Invoke(new Action(() => LBox_clients.Items.Add(name+" "+client.Client.RemoteEndPoint.ToString())));
            
            while (bClieantConnectet)
            {
                sData = reader.ReadLine();
                if (sData != null)
                {
                    LBox_chat.Invoke(new Action(() => LBox_chat.Items.Add(name + ": " + sData)));
                    writer.WriteLine("Du hast eine Nachricht erfolgreich gesendet");
                    writer.Flush();

                }
                if (sData == "ende")
                {
                    bClieantConnectet = false;
                    client.Close();
                    LBox_chat.Invoke(new Action(() => LBox_chat.Items.Add(name + " hat sich ausgeloggt")));
                    client.Close();
                    break;
                }
            }
        }

        public void cBox_aktualisieren()
        {
            while (true)
            {
                int counter = LBox_clients.Items.Count;
                if (counter != cBox_cliens.Items.Count)
                {
                    cBox_cliens.Invoke(new Action(() => cBox_cliens.Items.Clear()));
                    if (counter > 0)
                    {
                        for (int i = 0; i < counter; i++)
                        {
                            cBox_cliens.Invoke(new Action(() => cBox_cliens.Items.Add(LBox_clients.Items[i])));
                        }
                    }

                }
             
            }

        }


    }
}