Laden...

[erledigt]TCP Chat Socketadresse darf nur einmal verwendet werden und Prozess läuft weiter

Erstellt von Jan_kie vor 5 Jahren Letzter Beitrag vor 5 Jahren 4.637 Views
J
Jan_kie Themenstarter:in
11 Beiträge seit 2018
vor 5 Jahren
[erledigt]TCP Chat Socketadresse darf nur einmal verwendet werden und Prozess läuft weiter

Hallo,

ich soll für die Arbeit eine Art Chatanwendung programmieren, welche in beide Richtungen funktioniert. Da ich kompletter Anfänger bin was C# und besonders Netzwerktechnologien angeht, habe ich einige Probleme bei denen ich nicht weiter komme.

Wenn ich den Client und Server verbunden habe und beide Forms durch klicken auf das "rote X" beende laufen die Prozesse noch im Task-Manager und wenn ich diese Anwenungen erneut öffne und versuche verbinden zu lassen, kommt eine Fehlermeldung mit "Normalerweise darf jede Socketadresse (Protokoll, Netzwerkadresse oder Anschluss) nur jeweils einmal verwendet werden"

Ich habe auch schon versucht alles zu schleißen beim FormClosing-Event, bringt allerdings auch nichts.

        private void frmClient_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (t != null)
            {
                if (t.IsAlive)
                {
                    t.Abort();
                }
            }
            if (ns != null)
            {
                ns.Close();
            }
            if (client != null)
            {
                client.Close();
            }
            Application.Exit();
            this.Close();
        }

Hier der Code vom Server:

        public void DoWork()
        {
            byte[] bytes = new byte[1024];
            while (true)
            {
                int bytesRead = ns.Read(bytes, 0, bytes.Length);
                this.SetText(Encoding.ASCII.GetString(bytes, 0, bytesRead));
            }
        }

        private void SetText(string text)
        {
            if (this.textBox_Input.InvokeRequired)
            {
                SetTextCallback d = new SetTextCallback(SetText);
                this.Invoke(d, new object[] { text });
            }
            else
            {
                this.textBox_Input.Text = this.textBox_Input.Text + text;
            }
        }

        private void button_Starten_Click(object sender, EventArgs e)
        {
            IPAddress hostname = IPAddress.Parse(textBox_Hostname.Text);
            int portNum = Convert.ToInt32(textBox_Port.Text);
            listener = new TcpListener(hostname, portNum);
            listener.Start();
            client = listener.AcceptTcpClient();
            ns = client.GetStream();
            t = new Thread(DoWork);
            t.Start();
            textBox_Input.Text += "Verbindung hergestellt." + Environment.NewLine;
        }

und hier der Code vom Client:

        public void DoWork()
        {
            byte[] bytes = new byte[1024];
            while (true)
            {
                int bytesRead = ns.Read(bytes, 0, bytes.Length);
                this.SetText(Encoding.ASCII.GetString(bytes, 0, bytesRead));
            }
        }

        private void SetText(string text)
        {
            if (this.textBox_Input.InvokeRequired)
            {
                SetTextCallback d = new SetTextCallback(SetText);
                this.Invoke(d, new object[] { text });
            }
            else
            {
                this.textBox_Input.Text = this.textBox_Input.Text + text;
            }
        }

        private void button_Connect_Click(object sender, EventArgs e)
        {
            string hostName = textBox_Hostname.Text;
            int portNum = Convert.ToInt32(textBox_Port.Text);
            client = new TcpClient(hostName, portNum);
            ns = client.GetStream();
            t = new Thread(DoWork);
            t.Start();
            textBox_Input.Text += "Verbindung hergestellt." + Environment.NewLine;
        }

Ich hoffe ihr könnt mir helfen und ich kann noch was dazu lernen.

Mit freundlichen Grüßen

Jan_kie

16.835 Beiträge seit 2008
vor 5 Jahren

Du musst jeden Socket sauber schließen; siehe Implementierung von IDisposable und using()

4.939 Beiträge seit 2008
vor 5 Jahren

Du kannst auch die Threads als Hintergrund-Threads erstellen: Thread.IsBackground, so daß sich diese automatisch bei Prozessende mitbeenden.

J
Jan_kie Themenstarter:in
11 Beiträge seit 2018
vor 5 Jahren

Du kannst auch die Threads als Hintergrund-Threads erstellen:
>
, so daß sich diese automatisch bei Prozessende mitbeenden.

vielen Dank, das funktioniert!

Nur wenn ich jetzt eine der Anwendungen/Forms bei bestehender Verbindung schließe (Client oder Server) hängt sich die andere Anwendung/Form auf. Mal schauen wie ich das behoben bekomme.

T
2.224 Beiträge seit 2008
vor 5 Jahren

Wie dir Abt im anderen Thread empfohlen hat, nimm hier lieber Tasks und beende diese auch sauber.
Durch die aktuelle Lösung werden die Sockets von deiner Anwendung auch nicht sauber geschlossen.
Hier wäre es auch sinnvoll zu warten, bis dann der Task sauber beendet wurde und erst dann den Harten Abschluss durch Application.Exit() auszulösen.

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

16.835 Beiträge seit 2008
vor 5 Jahren

Threads können nur hart abgeschossen werden; Tasks können hingegen soft gecancelled werden, was hier die saubere Umsetzung wäre.