Entwickler-Ecke
Internet / Netzwerk - Client neu connecten lassen
ZO_orki - Do 01.06.06 22:21
Titel: Client neu connecten lassen
Hallo,
ich habe folgendes Problem: Ich habe einen Server und mehrere Clients (TServerSocket & TClientSocket). Wenn sich ein Client einloggt, funktioniert alles prima, ich kann Text hin und her jagen, etc. Das Problem: Wenn ein Client die Verbindung schließt und neu connecten will, bekomm ich die Fehlermeldung, dass ein Socket nur einmal verwendet werden darf. Logisch. Die Frage ist wie kann ich das umgehen? Wenn ich sowas probiere wie Socket.Close oder .Disconnect, dann spukt er mir immer Zugriffsverletztungsfehler aus.
Edit: Diese Probleme treten auf, wenn ich die Funktionen direkt auf das Socket, dass im OnClientDisconnect übergeben wird anwende. Wenn ich dagegen Socket.Connections[verbindung].Disconnect verwende, spukt er mir zwar keinen fehler aus, aber das neu connecten geht immer noch nicht. Das Socket mit .Free freigeben funktioniert übrigens auch nicht.
Hoffe ihr könnt mir weiterhelfen
MfG ZO_orki
Narses - Do 01.06.06 23:37
Moin!
Was tust du denn da nur... :gruebel: speziell hier:
ZO_orki hat folgendes geschrieben: |
| bekomm ich die Fehlermeldung, dass ein Socket nur einmal verwendet werden darf. |
Wer oder welches Objekt erzeugt diese Fehlermeldung?
ZO_orki hat folgendes geschrieben: |
Wenn ich sowas probiere wie Socket.Close oder .Disconnect, dann spukt er mir immer Zugriffsverletztungsfehler aus.
Edit: Diese Probleme treten auf, wenn ich die Funktionen direkt auf das Socket, dass im OnClientDisconnect übergeben wird anwende. |
Das brauchst und darfst du auch gar nicht. Wenn eine Seite die Verbindung trennt (ob Client oder Server ist egal), wird das entsprechende Socket-Objekt auf der anderen Seite der Verbindung automatisch mit entsorgt.
Ehrlich gesagt kann ich mir das nur als Konzept-Fehler in der Benutzung der Sockets erklären. Zeig mal den Code, so kommen wir da nicht weiter, weil du IMHO einen Fehler machst, den du gar nicht bemerkst. ;)
cu
Narses
ZO_orki - Fr 02.06.06 23:08
Dann geb ich mal meinen Code zum besten:
Der Server erstellt das Socket:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| Server := TServerSocket.Create(Form1); Server.Port := 8954;
Server.Open; Server.OnClientRead := Form1.TServerSocketRead; Server.OnClientConnect := Form1.OnClientConnect; Server.OnClientDisconnect := Form1.OnClientDisconnect; users := TStringList.Create; users.Sorted := False; IPs := TStringList.Create; IPs.Sorted := False; |
Der Client erstellt das Socket:
Delphi-Quelltext
1: 2: 3: 4: 5: 6:
| Client := TClientSocket.Create(Form1); Client.Port := 8954; Client.Host := wert; Client.Open; Client.OnRead := Form1.TClientSocketRead; |
Wenn der Client connected:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| procedure TForm1.OnClientConnect(Sender: TObject; Socket: TCustomWinSocket); VAR verbindung: Integer; BEGIN IPs.Add(Socket.RemoteAddress); users.Add(Socket.RemoteAddress); verbindung := users.IndexOf(Socket.RemoteAddress); Server.Socket.Connections[verbindung].SendText('/logy' + #13); END; |
Bis hierhin funktioniert alles prima.
Wenn der client offline geht:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17:
| procedure TForm1.OnClientDisconnect(Sender: TObject; Socket: TCustomWinSocket); VAR verbindung: Integer; BEGIN
verbindung := IPs.IndexOf(Socket.RemoteAddress); IPs.Delete(verbindung); users.Delete(verbindung);
Server.Socket.Connections[verbindung].Disconnect(0); Server.Socket.Connections[verbindung].Free;
END; |
Theoretisch könnte den Schluss auch draußen lassen (Nach dem Post über mir jedenfalls),
jedoch bekomme ich, wenn der Client nach dem Disconnect erneut versucht zu verbinden,
folgende Fehlermeldung (egal obs drinnen ist oder ob nicht):
"Windows-Socket-Fehler: Normalerweise darf jede Socketadresse (Protokoll, Netzwerk oder Anschluss) nur jeweils einmal verwendet werden (10048), auf API 'bind'"
Das spukt der Client aus. Der Server zeigt folgende Meldung an:
"Zugriffsverletzung bei Adresse 004261DE in Modul 'project1.exe'. Lesen von Adresse 1082E8CC"
Beim Compilieren bekomme ich keine Fehlermeldungen, da ist alles in Ordnung. Hoffe ihr könnt was damit anfangen und mir weiterhelfen.
Edit: Wenn ich die Fehlermeldung weckklicke und nochmal versuche zu connecten gehts irgendwie...
MfG ZO_orki
Narses - Sa 03.06.06 23:42
Moin!
Dachte ich´s mir doch, Konzeptfehler bei den Sockets. ;)
Erstmal das hier:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9:
| procedure TForm1.OnClientConnect(Sender: TObject; Socket: TCustomWinSocket); VAR verbindung: Integer; BEGIN IPs.Add(Socket.RemoteAddress); users.Add(Socket.RemoteAddress); verbindung := users.IndexOf(Socket.RemoteAddress); Server.Socket.Connections[verbindung].SendText('/logy' + #13); END; |
Das ist leider potentiell kaputter Code; du kannst dich nicht auf die Reihenfolge im Socketarray des Servers derart verlassen, dass eine externe Referenz als Index dient! Besser: Pack das Socket-Objekt in die .Objects[] der User-StringList und nimm .IndexOfObject(), um den Client in deiner Liste zu identifizieren; Nebeneffekt: dur brauchst das .Connections[]-Array im Serversocket nicht und kannst direkt den Wert aus .Objects[] verwenden. Habe ich
hier [
http://www.delphi-library.de/topic_ProtokollChatTutorial+TServerClientSocket++V201_54269.html] in meinem Code so gemacht, vielleicht ist das klarer im Beispiel. ;)
In diesem Code bist du etwas zu eifrig, du brauchst hier nix weiter zu tun, als deine eigenen Daten wegzuräumen, den Rest macht der ServerSocket schon ganz alleine: ;)
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
| procedure TForm1.OnClientDisconnect(Sender: TObject; Socket: TCustomWinSocket); VAR verbindung: Integer; BEGIN
verbindung := IPs.IndexOf(Socket.RemoteAddress); IPs.Delete(verbindung); users.Delete(verbindung);
END; |
cu
Narses
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2026 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!