Chat-Client-Server
-
Hallo Leute,
ich bin seit langer Zeit eifriger Mitleser in eurem Forum. Nun habe ich das erste Mal eine Frage.
Ich habe ein kleines Chat-System entwickelt. Als Bsp. haben mir diverse Seiten im Netz geholfen. Die ganze Sache funktioniert eigentlich, bis auf 2 kleine Ungereimtheiten.
1. Ich kann mich nur auf Port 1986 verbinden, versuche ich einen anderen Port dann funktioniert es überhaupt nicht mehr.
2. Wenn ich den Client schliesse kommt immer die Fehlermeldung "Der ChatClient funktioniert nicht mehr", "Es wird nach einer Lösung für das Problem gesucht".Der Code ist nicht besonders lang und gut kommentiert und Strukturiert:
Hier der Server-Code :
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Threading; using System.Net; using System.Net.Sockets; using System.IO; namespace ChatServer { public partial class Form1 : Form { private delegate void UpdateStatusCallback(string strNachricht); public Form1() { InitializeComponent(); } private IPAddress GetMyIP(ref IPAddress ipaAdr, string HostName) { IPAddress[] arrIP = Dns.GetHostEntry(HostName).AddressList; foreach (IPAddress IP in arrIP) if (IP.AddressFamily == AddressFamily.InterNetwork) { ipaAdr = IP; break; } if (ipaAdr == null) throw new Exception("Keine IPv4-Adresse gefunden!"); return ipaAdr; } public void Server_StatusChanged(object sender, StatusChangedEventArgs e) { this.Invoke(new UpdateStatusCallback(this.UpdateStatus), new object[] { e.EventMessage }); // Server wird upgedated } private void UpdateStatus(string strNachricht) { txtServer.AppendText(strNachricht + "\r\n"); // Neue Nachricht im Serverfenster anzeigen } private void Form1_Load(object sender, EventArgs e) { try { this.Show(); Application.DoEvents(); } catch (Exception exp) { MessageBox.Show("Server konnte nicht geöffnet werden!","Applicatin Error" + exp, MessageBoxButtons.OK, MessageBoxIcon.Exclamation); } } private void btnIPaut_Click(object sender, EventArgs e) { IPAddress ipaAdr=null; try { GetMyIP(ref ipaAdr, Dns.GetHostName()); MyConn(ref ipaAdr); btnStart.Enabled = false; txtIP.Enabled = false; } catch (Exception exp) { MessageBox.Show("Server konnte nicht geöffnet werden!", "Applicatin Error" + exp, MessageBoxButtons.OK, MessageBoxIcon.Exclamation); } } private void btnStart_Click(object sender, EventArgs e) { if (txtIP.Text == "") { MessageBox.Show("Sie müssen eine gültige IP eingeben", "IP-Eingabe_Fehler", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); } else { IPAddress ipaAdr = IPAddress.Parse(txtIP.Text); MyConn(ref ipaAdr); btnIPaut.Enabled = false; } } private void Meldung(string myMsg) { txtServer.AppendText(myMsg + "\r\n"); // Nachricht im Serverfenster anzeigen } private void MyConn(ref IPAddress ipaAdr) { btnIPaut.Enabled = false; ChatServer Server = new ChatServer(ipaAdr);// Neue Instanz des Serverobjektes anlegen ChatServer.StatusChanged += new StatusChangedEventHandler(Server_StatusChanged); Server.StartListening(); // Auf Verbindungen warten Meldung("Warte auf Verbindung...\r\n"); // Anzeige des Warten-Status im Serverfenster } } }
Hier der Client Code :
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Net; using System.Net.Sockets; using System.IO; using System.Threading; namespace ChatClient { public partial class Form1 : Form { private StreamReader srrEmpfaenger; private StreamWriter swrSender; private TcpClient MyTcpServer; private delegate void CloseConCallback(string strGrund); // Trennen private delegate void UpdateStateCallback(string strMessage); // NachrichtenUpdate private Thread trdThreading; private IPAddress ipaAdr; private bool bolConnection; private string strName = ""; public Form1() { Application.ApplicationExit += new EventHandler(OnApplicationExit); // Event-Handler für das // Schliessen des Prg.' InitializeComponent(); } public void OnApplicationExit(object sender, EventArgs e) // Das Prg. wird geschlossen { if (bolConnection == true) // ... besteht noch eine Verbindung, dann... { srrEmpfaenger.Close(); // ... Empfänger-Stream schliessen swrSender.Close(); // ... Sender-Stream schliessen bolConnection = false; // ... Verbindung trennen MyTcpServer.Close(); // ... TcpServer schliessen } } private void btnStart_Click(object sender, EventArgs e) { int intToggle = 0; // Schalter um zu entscheiden ob IP-Adresse atomatisch bezogen oder von // Hand eingegeben wurde (Start gedrückt) if (bolConnection == false) // Falls keine Verbindung besteht ... { InitCon(intToggle); // ... Verbindung herstellen } else // Wenn eine Verbindung besteht ... { ClsCon("Verbindung durch Benutzer getrennt."); // ... Verbindung trennen } Ctrl_ausschalten(); } private void Ctrl_ausschalten() { txtChatName.Enabled = false; // Textfeld für ChatNamen ausschalten txtServerIPAdresse.Enabled = false; // Textfeld für ServerIP-Adresse ausschalten btnIPaut.Enabled = false; // Button um IP-Adresse autom. zu bez. ausschalten btnStart.Enabled = false; // Button um Verbindung aufzubauen ausschalten } private void InitCon(int intToggle) // Funktion für den Verbindungsaufbau { ipaAdr = null; // IpaAdr mit "null" belegen int intStatus = intToggle; if(intStatus == 0) { ipaAdr = IPAddress.Parse(txtServerIPAdresse.Text); // IP-Adresse (Text) in IPAddress-Objekt parsen }else if (intStatus == 1) { GetMyIP(ref ipaAdr, Dns.GetHostName()); // IP-Adresse automatisch beziehen } MyTcpServer = new TcpClient(); // Neues TcpClient-Objekt (MyTcpServer) anlegen MyTcpServer.Connect(ipaAdr, 1986); // Neue Verbindung mit IP-Adresse (ipaAdr) bolConnection = true; // Variable um festzustellen ob eine Verbindung // besteht // Nichtbenutzte Controls ausschalten bzw. benutzte einschalten txtChatName.Enabled = false; txtServerIPAdresse.Enabled = false; btnSenden.Enabled = true; txtSNachricht.Enabled = true; strName = txtChatName.Text; // Chat Name in Variablen speichern swrSender = new StreamWriter(MyTcpServer.GetStream()); // ChatName an Server übermitteln swrSender.WriteLine(txtChatName.Text); swrSender.Flush(); trdThreading = new Thread(new ThreadStart(EmpfangeNachrichten)); // Den Thread für die trdThreading.Start(); // Kommunikation starten } private void ClsCon(string strGrund) // Funktion zum Trennen einer Verbindung { txtAusgabe.AppendText(strGrund + "\r\n"); // Grund für das Schliessen im Ausgabefenster darstellen // Nichtbenutzte Controls ausschalten bzw. benutzte einschalten txtChatName.Enabled = true; // Textfeld für ChatNamen einschalten txtServerIPAdresse.Enabled = true; // Textfeld für ServerIP-Adresse einschalten btnSenden.Enabled = false;// Button um Nachrichten zu verschicken ausschalten txtSNachricht.Enabled = false;// Textfeld für zu versendende Nachrichten ausschalten bolConnection = false; // Verbindung trennen swrSender.Close(); // Sender-Stream trennen srrEmpfaenger.Close(); // Empfaenger-Stream trenne MyTcpServer.Close(); // TcpServer schliessen } private void EmpfangeNachrichten() // Funktion zum handeln empfangener Nachrichten { srrEmpfaenger = new StreamReader(MyTcpServer.GetStream()); // Antwort vom Server erhalten string strConAntwort = srrEmpfaenger.ReadLine(); // Wenn der 1. Buchstabe der Nachricht eine 1 if (strConAntwort[0] == '1') // dann war die Verbindung erfolgreich { // Meldung über Erfolg der Nachricht in Ausgabebox schreiben this.Invoke(new UpdateStateCallback(this.UpdateAusgabe), new object[] { "Verbindung erfolgreich!!!!" }); } else // War der 1. Buchstabe keine 1 (die Verbindung hat nicht geklappt) ... { string strGrund = "Es kan keine Verbindung zu Stande : "; // ... dann Meldung über Misserfolg und // den Grund dafür strGrund += strConAntwort.Substring(2, strConAntwort.Length - 2);// in der Ausgabebox this.Invoke(new CloseConCallback(this.ClsCon), new object[] { strGrund }); // darstellen return; } while (bolConnection) // Solange die Verbindung besteht.... { // einkommende Nachrichten lesen und in der Ausgabebox darstellen this.Invoke(new UpdateStateCallback(this.UpdateAusgabe), new object[] { srrEmpfaenger.ReadLine() }); } } private void UpdateAusgabe(string strNachricht) // Funktion zum updaten der AusgabeBox { txtAusgabe.AppendText(strNachricht + "\r\n"); // Text anhängen } private void NachrichtAbschicken() // Funktion um eingegebene Nachrichten an den Server zu schicken { if (txtSNachricht.Lines.Length >= 1) { swrSender.WriteLine(txtSNachricht.Text); swrSender.Flush(); txtSNachricht.Lines = null; } txtSNachricht.Text = ""; } private void btnSenden_Click(object sender, EventArgs e) // Funktion um Nachrichten mit dem { // "Nachricht abschicken"-Butteon zu verschicken NachrichtAbschicken(); } private void txtMessage_KeyPress(object sender, KeyPressEventArgs e) // Funktion um { // Nachrichten auch durch das Betätigen des "Return"-Buttens zu verschicken if (e.KeyChar == (char)13) // Prüfen ob "Return"-Taste (char)13 gedrückt wurde ... { NachrichtAbschicken(); // ... dann Nachricht abschicken } } private void Form1_Load(object sender, EventArgs e) { this.Show(); } private IPAddress GetMyIP(ref IPAddress ipaAdr, string HostName) // Funktion um IP-Adresse automatisch zu ermitteln { IPAddress[] arrIP = Dns.GetHostEntry(HostName).AddressList; foreach (IPAddress IP in arrIP) if (IP.AddressFamily == AddressFamily.InterNetwork) { ipaAdr = IP; break; } if (ipaAdr == null) throw new Exception("Keine IPv4-Adresse gefunden!"); return ipaAdr; } private void btnIPaut_Click(object sender, EventArgs e) { int intToggle = 1; if (bolConnection == false) // Falls keine Verbindung besteht ... { InitCon(intToggle); // ... Verbindung herstellen Ctrl_ausschalten(); } else // Wenn eine Verbindung besteht ... { ClsCon("Verbindung durch Benutzer getrennt."); // ... Verbindung trennen } } } }
Wäre super wenn Ihr mir helfen könntet.
MfG,
john_questioneer
-
-
Dir lässt sich leider nur sehr schwer helfen. Denn der Code ist sehr lang und sehr unübersichtlich...
Wenn es mit einem Port bereits funktioniert, dann sollte ein anderer Port eigentlich keine Probleme bereiten. Mir fällt dazu keine Erklärung ein. Startest du das Programm zur Änderung des Ports neu? Wenn nicht, dann könnte es sein, dass du die alte Verbindung nicht richtig schließt und daher keinen anderen Port wählen kannst.
Wenn es beim Schließen des Programms eine Fehlermeldung gibt, dann solltest du den Debugger nutzen, um festzustellen wo dieser Fehler auftritt. Ich könnte mir vorstellen, dass du damit einen Verbindungsabbruch o.ä. erzeugst und dann eine Exception geworfen wird.
Alternativ könntest du auch mit einem anderen Tool (z.B. Putty, DebugTCP-Tool) versuchen einen Client/Server zu simulieren, um sicherzustellen, dass der Client/Server korrekt arbeitet.