Hallo zusammen
Ich habe ein Problem, dass der Server teilweise keine Meldungen an den Client schicken kann.
Der Aufbau ist wie folgt:
Server:
Der Server horcht auf alle einkommenden Verbindungen auf einem Port. Sobald eine ankommt wird die TCPClient Instantz in ein neuen Thread übergeben und wartet dort dann auf einkommende Nachrichten.
Client:
Der Client verbindet sich zum Server und auch dieser läuft in einem eigenen Thread der bei
string str = new StreamReader(this.client.GetStream()).ReadLine();
wartet bis etwas ankommt.
Nun ist es teilweise so, dass zwar der Client noch Nachrichten an den Server senden kann und diese vom Server auch verarbeitet werden, jedoch der Server nichts an den Client schicken kann.
Als Übertragung verwende ich einen StreamWriter (Client)
StreamWriter writer = new StreamWriter(client.GetStream());
writer.WriteLine("senden");
writer.Flush();
Auf der Serverseite
NetworkStream stream = null;
try
{
stream = clientByNames[receiverName].GetStream(); // Da ist die Clientinstanz dahinter
}
catch
{
//Fehler
}
if (stream != null)
{
StreamWriter writer = new StreamWriter(stream);
stream.Flush();
writer.WriteLine("send");
writer.Flush();
}
Ich habe mich bei dem Server eingeklinkt und konnte im Debugmodus sehen (wenn ich das richtig intepretiert habe) das er bei writer.Flush() stehengeblieben ist.
Die Frage ist nun, ob diese Infos reichen um mir einen Anhanltspunkt geben zu können wo das Problem liegen könnte, oder ob das Problem "bekannt" ist und ich einen Fehler bei der Implementierung mache.
Evtl. müssen zuerst noch die richtigen Fragen gestellt werden 😉
Besten Dank für eure Hilfe
Hallo Pioneer17,
vor kurzem gab es ein ziemlich ähnliches Problem.
Schau mal hier: Socket Server mit Threads, vom GUI aus dem Client etwas schicken
Client:
Der Client verbindet sich zum Server und auch dieser läuft in einem eigenen Thread der beistring str = new StreamReader(this.client.GetStream()).ReadLine();
Warum erstellst du den StreamReader hier immer wieder ?
André
Hi TheGear
danke für den Hinweis.
Es gibt keinen speziellen Grund warum ich den StreamReader immer wieder erstelle. Das wäre ja "nur" eine Speicheroptimierung, oder?
Betreffend des anderen Beitrages, sehe ich keinen Zusammenhang mit meinem Problem. Ich muss es sowieso einbisschen im Auge behalten, da es ja nicht immer auftritt.
Ich habe in meinem Programm die komplette Kommunikaitons geändert, evtl. kam dieser Fehler noch von "Altlasten" vom Alten Code. Mittlerweile ist der "Umbau" soweit fertig und bis jetzt ist es nicht wieder passiert.
Leider ist es wieder passiert...
ist das eigentlich so, dass händisch einen Sleep eingebaut werden muss, bevor ich z.B. die Verbindung beende, oder bei einem Connect, bevor ich die erste Meldung schicke?
Wo ich porbleme hatte war wenn ich eine Meldung geschickt hatte und gleich darauf die Verbindung mit .Disconnect beendet habe ging die letze Meldung teilweise nicht durch. Seit dem ich vor dem Disconnect einen Sleep von 500ms eingebaut habe, ist das nicht mehr passiert.
Muss ich das ggf. auch vor dem ersten senden einer Nachricht machen?
Ist das "normal"?
Das immer neue erstellen des StreamReaders ist nicht nur eine optimierung. Der StreamReader speichert Daten zwichen. Wenn du dann einen neuen erstellst gehen die gecachten Daten verloren
Als Kommunikations- "Vorlage" habe ich das Projekt Chatprogramm verwendet.
Server:
private void ListenToClient(object aClient)
{
TcpClient senderClient = (TcpClient)aClient;
bool flag = true;
while (flag)
{
try
{
string str = new StreamReader(senderClient.GetStream()).ReadLine();
if (!string.IsNullOrEmpty(str))
{
this.ParseReceivedTelegram(senderClient, str);
}
else
{
flag = false;
}
}
catch (IOException)
{
flag = false;
}
}
}
Da ist es doch richtig, dass der StreamReader immer wieder neu erstelt wird, oder? Es werden ja sowiso alle Daten gelesen und gleich weiter gegeben, oder sehe ich das falsch?
Mein Projekt habe ich soweit umgestellt, dass es mehrere Server gibt.
Bsp.:
Ich habe eine Hauptapplikation "Service" und mehrere Hilfsprogramme die verteilt sind. Entgegen der Norm, sind bei mir diese Hilfsprogramme die Server (Klassen) und das Hauptprogramm der Service eigenltich der Client. Der Service verbindet sich mit den Hilfsprogrammen.
Vom Service her können aber mehrere Verbinungen pro Hilfsprogramm hergestellt werden.
Wenn das Problem jedoch auftritt, dass die Hilfsprogramme (Server) nichts mehr an den Service (Client) senden können betrifft das alle Server. D.h. der Fehler dürfte nicht serverseitig sein, sondern eher clientseitig.
Hallo Pioneer17,
Da ist es doch richtig, dass der StreamReader immer wieder neu erstelt wird, oder? Es werden ja sowiso alle Daten gelesen und gleich weiter gegeben, oder sehe ich das falsch?
Nein. Es wird ein neuer Stream erzeugt der dann bis zum nächstem Zeilenumbruch (eines Strings) Daten des zugrunde liegenden Streams liest.
Allerdings wird bei Operationen wie beispielsweise Close auch der zugrundeliegende Stream geschlossen.
So wie du es derzeit machst, sind alle Vorteile von Streams für die Katz.
Wo ist denn das Problem den StreamReader nur einmal zu erstellen ?
André
Hab die ganze Geschichte nun soweit umgebau, dass ich nun direkt in den Stream schreibe, bzw lese mit stream.write / stream.read.
weiter hatte ich das problem, dass mehrere Datensätze im Streamreader waren, welche ich mit jeder neuen Instanz "zerstört" habe. Das war der Grund, warum ich teilweise gewisse Sachen nicht empfangen habe und teilweise nur die Hälfte.
Nun seit dem umbau funktioniert alles so wie ich mir das vorgestellt habe.
Nun erstelle ich einen Stream pro Verbindung und merke mir diese in einem Dic, damit ich dann später wieder etwas in den stream zurück schicken kann. Somit wird für die Lebensdauer der Verbindung lediglich noch ein Networkstream-Instanz gespeichert.