Autor Beitrag
Tobi482
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 135



BeitragVerfasst: Di 02.05.06 11:27 
Hi Leute,

ich habe ein Problem mit dem organisieren von multiplen Verbindungen auf einen Server. Ich kenne die Winsock (ActiveX) sehr gut und habe versucht einen alten VB Code von mir in Delphi umzuschreiben. Dabei bin ich auf folgendees Proglem gestoßen.

Ist die TTcpServer Delphi Komponente erstmal richtig eingestellt und befindet sich im Listen-Mode, wird ja bei jedem erfolgreichem Verbindungsaufbau das OnAccept Event aufgerufen. Bei gescheitertem Verbidnungsaufbau OnError.

Das übergebene Parameter [ClientSocket: TCustomIpClient] veweist dabei auf ein Objekt, welches die frisch aufgebaute Verbindung repräsentiert. Mein Problem war nun, dass sobald diese procedure durchgelaufen ist, verschwindet mit dem Free'en des Stacks auch gleichzeitig der Verweis auf die Verbidnung :-(.

Ich möchte nicht für jedes kleine Datenpaket eine neue Verbidnung zum Server aufbauen. Daher liegt der Schluss nahe, diese Verbindungen zu sichern, und erst dann wieder freizugeben, wenn ich es für nötig halte.

Daher wollte ich einen Thread erstellen, dem ich dieses Verbindungsobjekt übergebe. Erst ,wenn ich den Thread sage er darf ausgehen, wird das Verbinugnsobjekt freigegeben. Während der Thread läuft darf ich mit der Verbinung alles noch machen was ich möchte.

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
Type
     TCP_Thread = class(TThread)
          public
               connection     : TCustomIpClient;
          protected
               procedure Execute; override;
     end;
-------------------------------------------
procedure MyServer.Accept(Sender: TObject; ClientSocket: TCustomIpClient);
var
     i    : integer;
begin
     for i := 0 to max_con do
     begin
          if connection[i] = nil then
          begin
               //false = Thread gleich starten
               //true = warten bis Resume aufgreufen wird
               connection[i] := TCP_Thread.Create(true);
               connection[i].connection := ClientSocket;
               connection[i].Resume;
               break;
          end;
     end;
end;


ich habe also ein Array von Threads erstellt "connection[i]", das die Anzahl meiner möglichen Verbindungen darstellt. Wird das On Accept Event ausgelöst so prüfe ich welches der Array Elemente noch auf keine erstelltes Objekt verweist "if connection[i] = nil then". Ist eines gefunden, so wird es erstellt und der von OnAccept erzeugt Verbindungsverweis "ClientSocket" wird ebenfalls dem Thread Übergeben.

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
procedure TCP_Thread.Execute;
var
     data : string;
begin
     while connection.Connected = ture do
     begin
          if connection.BytesReceived > 0 then
          begin
               data := connection.Receiveln();
               //mach mit Daten was du willst
               //noch nicht gecodet^^
          end;
          Sleep(1000);
     end;
end;


Der Thread sollte nun solange laufen bis die verbindung abgebaut wird "while connection.Connected = ture do". Ob server- oder clientseitiger Abbau ist dabei egal.

Soweit zu der Idee, die nicht funktioniert :-[.

DAS PROBLEM:

Im Thread steht "connection.Connected = ture" nie auf true :-(.

Meine Vermutung !!!

Ich führe dies auf die Zeile
ausblenden Delphi-Quelltext
1:
connection[i].connection := ClientSocket;					

zurück. Vermutlich wird dabei eine Kopie des Objektes erzeugt und dem Thread übergeben. Diese Kopie sieht zwar genauso aus wie das wirkliche Objekt hat aber keiner Verbindung zum Netz. Es ist ein Abbild des Objektes zum dem Zeitpunkt als es kopiert wurde. Die Kopie wird also nie Daten empfangen. Das wahre Objekt scheint mit Beedigung von OnAccept wieder verloren gegangen zu sein.

Auch wenn ich connection als Pointer auf eine Verbindung deklariere und in OnAccept setzte, so verweist es im Thread wieder auf nil :-[.

FRAGE

Wie kann ich der Zerstörung des Verbindungsobjektes entgegen wirken, damit ich nicht immer einer neue Verbidnung aufbauen muss?

Mit freundlichen Grüßen
Tobi
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10185
Erhaltene Danke: 1261

W11x64
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Di 02.05.06 23:32 
Moin!

Und du bist sicher, dass du (vielleicht auch erstmal) mit TServerSocket und TClientSocket nicht weiter kommst? Wenn ich mir das so ansehe, dann läuft das erstmal darauf hinaus.

Wenn dir die Sockets nicht "behagen", dann schau dir doch lieber mal die Indy-Komponenten an, anstatt "das Rad neu zu erfinden". ;)

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
Tobi482 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 135



BeitragVerfasst: Mi 03.05.06 12:44 
Hi,

erstmal Danke für deine Antwort :-D

mhh du kannst dir sicherlich vorstellen, dass dieser vorschlag etwas Unbahgen in mir verbreitet. Das ist so wie Aufgeben .... ich bin eine Kämpfernatur und ein Dickkopf :-P

Ist mein Problem denn eigentlich rüber gekommen? oder soll ich noch ein paar angaben machen.

PS: Im Prinzip gibt es kaum unterschiede im Aufbau zwischen Indy und diesen Sockets. Auch die Indy-Server-Komponenten übergeben einen Thread oder eine Art Verbindungsobjekt. Ich denke da stoße ich auf das gleich Problem. Winsocks sind da echt super einfach zu handeln. Habe die auch schon importiert und funktionieren Prima .... NUR .... das ist eklig. VB + ActiveX + Delphi .... das stinkt doch gerade vor Kompatiblität. Und ein schöner Stil ist das außerdem auch nicht.

Ich weiß ich weiß ich bin mäkelig, aber da gegen kann ich nix machen :-D

Wenn dir und irgendwem eine Idee kommt oder jemand ein Sourcecode hat der ähnliches macht, wenn auch durch anderen Mittel, dann bitte ich um Antwort.

Mit freundlichen Grüßen
Tobi