Autor Beitrag
IhopeonlyReader
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 600
Erhaltene Danke: 23


Delphi 7 PE
BeitragVerfasst: Di 18.06.13 20:32 
Guten Tag,
bei einem "direktBefehl" wo NUR Daten hingeschickt werden, ist mir etwas nerviges aufgefallen..
(Zum Server: Dieser empfängt die Daten und gibt sie in einem Memo aus (Testgründe) )
Bei folgendem Code, wurde NICHTS übertrage:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
var ClientT: TClientSocket;
begin
ClientT := TClientSocket.create( nil );
ClientT.Host := DieIP; // hier steht halt meine IP (ja, die stimmt ! )
ClientT.Port := 123456//Beispielport
ClientT.Open; 
ClientT.Socket.SendText( '1' ); //Zum testen irgendein String schicken
//ClientT.Socket.Connected //würde FALSE zurückliefer.. (weil noch keine Zeit zum verbinden gelassen wurde)
ClientT.Socket.SendText( 'test' ); //eigentlich zu sendender String
//ClientT.Close; //müsste geschehen, aber sonst gibt's nur noch mehr Fehler (vom Server, da Socket nicht exisitier !?)
//ClientT.Free;  //wieder Fehler vom Server
end;


Am Server kommt nichts an!
Wenn ich wie im Beispiel Close und Free wegnehme, dann wird angezeigt, dass verbunden wurde (onClientWrite wird aufgerufen)
der 1 String (im Beispiel "4") wird nicht übergeben.. fehlt komplett...
Der string 'test' (über onclientread) kommt sogar VOR dem "verbinden" (clientwrite)

Wie muss ich wo warten?
Application.ProcessMessages und sleep bringen nichts !

_________________
Sucht "neueres" Delphi :D
Wer nicht brauch was er hat, brauch auch nicht was er nicht hat!
FinnO
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1331
Erhaltene Danke: 123

Mac OSX, Arch
TypeScript (Webstorm), Kotlin, Clojure (IDEA), Golang (VSCode)
BeitragVerfasst: Di 18.06.13 21:06 
Moin,

du hast auch nen Durchsatz...
www.entwickler-ecke....c_60744.html?view=dl

Prost,
IhopeonlyReader Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 600
Erhaltene Danke: 23


Delphi 7 PE
BeitragVerfasst: Di 18.06.13 21:27 
user profile iconFinnO hat folgendes geschrieben Zum zitierten Posting springen:
du hast auch nen Durchsatz...

Tut mir leid, verstehe ich nicht :oO:
Und dein tutorila ist zwar hilfreich, wusste ich aber schon...
Wo das Problem liegt, denke ich ja zu wissen.. aber wie kann man das ganze in 1 procedure machern? (Client erstellen, verbinden, text schicken, disconecten, Client freigeben) ohne entsprechendes Delay etc? oder wenigstens nur mit dem Minimum an notwendiger "Wartezeit"

_________________
Sucht "neueres" Delphi :D
Wer nicht brauch was er hat, brauch auch nicht was er nicht hat!
FinnO
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1331
Erhaltene Danke: 123

Mac OSX, Arch
TypeScript (Webstorm), Kotlin, Clojure (IDEA), Golang (VSCode)
BeitragVerfasst: Di 18.06.13 21:34 
Du musst das Ereignis OnConnect nutzen, ist das, was ich aus Narses' Tutorial mitnehme.

Zitat:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
// Verbindung erfolgt (connect) -> Meldung machen
procedure TForm1.ClientSocket1Connect(Sender: TObject; Socket: TCustomWinSocket);
begin
  Log.Lines.Add('Verbunden mit '+ServerAdress.Text);
end;
IhopeonlyReader Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 600
Erhaltene Danke: 23


Delphi 7 PE
BeitragVerfasst: Di 18.06.13 22:09 
Vielen Dank :)
So funktionierts
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
//uses ScktComp;
//var ClientT: TClientSocket; //leider global deklariert
procedure TForm1.ClientTOnConnect(Sender: TObject; Socket: TCustomWinSocket);
    begin
    ClientT.Socket.SendText( Edit1.Text );
    sleep( SizeOf(Edit1.Text) ); //zeit zum übertragen geben
    ClientT.Close;
    ClientT.Free;
    end;

procedure TForm1.Button1Click(Sender: TObject);
begin
ClientT := TClientSocket.create( nil );
ClientT.Host := 'localhost';
ClientT.Port := 12345//Beispielport
ClientT.OnConnect := ClientTOnConnect;
ClientT.Open;
end;


Edit: die Variable muss doch nicht global deklariert werden :freu:
Dazu muss die Procedure zu abgeändert werden:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
procedure TForm1.ClientTOnConnect(Sender: TObject; Socket: TCustomWinSocket);
    begin
    TClientSocket(Sender).Socket.SendText( Edit1.Text );
    sleep( SizeOf(Edit1.Text) ); //zeit zum übertragen geben
    TClientSocket(Sender).Close;
    TClientSocket(Sender).Free;
    end;

Ich gehe davon aus, dass als Sender nur der "Auslöser" gemeint sein kann, und somit das TClientSocket

Nachtrag: Sleep ist unnötig, da ein String nur ein Zeiger auf ein Array of Char ist.. somit immer die größe von 4 hat. sleep(4) ist insg. unnötig

_________________
Sucht "neueres" Delphi :D
Wer nicht brauch was er hat, brauch auch nicht was er nicht hat!
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19315
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Di 18.06.13 22:25 
Den Sender in einer eigenen Ereignisroutine freizugeben ist keine gute Idee. Meistens wird nach dem Aufruf deiner Ereignis-Prozedur noch auf die Komponente zugegriffen, und da die dann schon freigegeben ist, knallt das ggf. gewaltig. Wenn du Glück hast, wird nur Speicher an den Stellen gelesen und es passiert nichts, aber ein Fehler ist das trotzdem.

Aus solchen Sachen resultieren jedenfalls gerade bei größeren Programmen schwer zu findende Probleme, die sich ganz woanders äußern. Heißt: Beide Varianten sind äußerst bedenklich...
IhopeonlyReader Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 600
Erhaltene Danke: 23


Delphi 7 PE
BeitragVerfasst: Di 18.06.13 22:41 
kennst du bessere Vorschläge? wie z.B. das Close und free in einen Timer setzten.. nebenbei eine boolean variable deklarieren, die beim OnConnect auf True gesetzt wird.. der timer wird nur ausgeführt, wenn diese variable true ist...

das wäre noch unsauberer meiner Meinung nach.. aber "sicherer"

_________________
Sucht "neueres" Delphi :D
Wer nicht brauch was er hat, brauch auch nicht was er nicht hat!
IhopeonlyReader Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 600
Erhaltene Danke: 23


Delphi 7 PE
BeitragVerfasst: Mi 19.06.13 16:21 
dazu noch eine Frage, wann wird der Client (denn endlich) connected?
Wenn man eine Schleife macht wo man Clients erstellt und verbindet, dann verbindet er den 1 Client erst, wenn die schleife durch ist...

_________________
Sucht "neueres" Delphi :D
Wer nicht brauch was er hat, brauch auch nicht was er nicht hat!
>M@steR<
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 288
Erhaltene Danke: 3



BeitragVerfasst: Mi 19.06.13 16:42 
Gelöscht


Zuletzt bearbeitet von >M@steR< am Di 17.09.13 03:09, insgesamt 1-mal bearbeitet
IhopeonlyReader Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 600
Erhaltene Danke: 23


Delphi 7 PE
BeitragVerfasst: Mi 19.06.13 18:25 
ok, also muss ich das ganze in ein extra thread einlagern.. schade

_________________
Sucht "neueres" Delphi :D
Wer nicht brauch was er hat, brauch auch nicht was er nicht hat!
IhopeonlyReader Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 600
Erhaltene Danke: 23


Delphi 7 PE
BeitragVerfasst: Mi 19.06.13 20:46 
Für alle die es interessiert ;)
Ich habe es nun umgesetzt, dass
- ein Client erstellt wird
- Host, IP gesetzt werden
- verbunden wird
- ein String gesendet wird
- getrennt wird
- der Client freigegeben wird
und das alles in einer While-Schleife !

Hier der Code ;)

Thread:
ausblenden volle Höhe 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:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
unit uTSent;
interface
uses
  Classes, ScktComp;
type
  TSent = class(TThread)
  private
    DerClient: TClientSocket;
    ZuSenden: String;
    fFertig,
    fGeklappt: Boolean;
    procedure ClientTOnConnect(Sender: TObject; Socket: TCustomWinSocket);
    procedure ClientTOnError(Sender: TObject; Socket: TCustomWinSocket; ErrorEvent: TErrorEvent; var ErrorCode: Integer);
  protected
    procedure Execute; override//wird nicht benötigt
  public
    property Fertig: Boolean read fFertig;
    property Geklappt: Boolean read fGeklappt;
    constructor create( IP: String; Port: Word; ZuSendenderText: String );
  end;

implementation

procedure TSent.ClientTOnConnect(Sender: TObject; Socket: TCustomWinSocket);
begin
  try
  Socket.SendText( ZuSenden );
    except
    fGeklappt := False;
    end;
DerClient.Close;
DerClient.Free;
fFertig := True;
end;

procedure TSent.ClientTOnError(Sender: TObject; Socket: TCustomWinSocket; ErrorEvent: TErrorEvent; var ErrorCode: Integer);
begin
ErrorCode := 0//kann ggf. angepasst werden, da ich die Variable fGeklappt habe, weiß ich auch so ob es geklappt hat oder nicht
fGeklappt := False;
DerClient.Close;
DerClient.Free;
fFertig := True;
end;


constructor TSent.create( IP: String; Port: Word; ZuSendenderText: String );
begin
inherited create( true ); //muss erstellt werden, der Parameter ist in diesem
//Sonderfall egal, da die in diesem Thread auszuführenden Proceduren nicht "Execute" sondern die "Wichtigen" von unten sind
fFertig := False;
fGeklappt := True; //falls nichts schiefgeht, wird es geklappt haben
DerClient := TClientSocket.Create( nil ); 
DerClient.Host := IP;
DerClient.Address := IP; //Sicher ist sicher
DerClient.Port := Port;
ZuSenden := ZuSendenderText;
DerClient.OnConnect := ClientTOnConnect;  //WICHTIG
DerClient.OnError := ClientTOnError;      //   "
DerClient.Open;
end;


procedure TSent.Execute;
begin
//leer (wird nicht benötigt)
end;

end.

Hier gibt es den Super-seltenen-Sonderfall, dass beim erstellen des Threads es völlig egal ist, ob er suspended ist oder nicht !

Ein Beispiel der Nutzung
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
procedure TForm1.Button1Click(Sender: TObject);
var EThread: TSent; 
begin
EThread := TSent.create( 'localhost', StrToInt(EPort.Text), ENachricht.Text );
while not EThread.Fertig do //Dauerschleife
  begin
  Application.ProcessMessages; //damit es sich nicht aufhängt
  end;
//Ab hier ist der Thread fertig
  if EThread.Geklappt then
    Showmessage( 'Fertig und Geklappt' )
  else
    Showmessage( 'Fertig, aber Fail' );
  EThread.Free;
end;

Nach der ersten Ausführung werden 1416 KB mehr benötigt, ich weiß leider nicht warum.. aber es wird nach mehrfacher Ausführung nicht mehr ! somit wird nicht vergessen irgendetwas freizugeben...

_________________
Sucht "neueres" Delphi :D
Wer nicht brauch was er hat, brauch auch nicht was er nicht hat!
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19315
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mi 19.06.13 20:57 
Dass du da gar keinen Thread wirklich benutzt, ist dir aber schon klar, oder? Im Thread wird ausschließlich das ausgeführt was in OnExecute steht. Du kannst die Klasse genausogut bzw. sinnvoller gar nicht erst von TThread ableiten.
IhopeonlyReader Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 600
Erhaltene Danke: 23


Delphi 7 PE
BeitragVerfasst: Mi 19.06.13 21:12 
nein, habe ich ausprobiert !
die proceduren ClientTOnConnect und ClientTOnError werden, falls sie ausgelöst werden, im Thread ausgelöst !

_________________
Sucht "neueres" Delphi :D
Wer nicht brauch was er hat, brauch auch nicht was er nicht hat!
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19315
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mi 19.06.13 21:27 
Lass dir einfach mit GetCurrentThreadId die ID des aktuellen Threads ausgeben (einmal in OnConnect und einmal in deinem Hauptthread) oder schau in die Liste der Threads in Delphi.

Davon abgesehen:
Nimm einfach das (TThread) hinter class weg und du wirst sehen, dass es 1:1 genauso funktioniert...
IhopeonlyReader Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 600
Erhaltene Danke: 23


Delphi 7 PE
BeitragVerfasst: Mi 19.06.13 21:33 
tatsächlich.. dass es funktioniert liegt am Application.ProcessMessages;
mhhh.. aber gibt es soetwas auch in "threads"? da gibt es ja keine application

_________________
Sucht "neueres" Delphi :D
Wer nicht brauch was er hat, brauch auch nicht was er nicht hat!
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10183
Erhaltene Danke: 1256

W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Mi 19.06.13 22:53 
Moin!

Lieber Gott, was tust du denn da nur immer wieder... :hair: Willst du Reifenhändler werden oder warum erfindest du die Dinger immer wieder neu?! :rofl:

Wenn du einen synchronen Socket haben willst, dann stell doch einfach die Eigenschaft .ClientType auf ctBlocking und gut ist, dann gibt´s auch keine Ereignisse mehr. Dann aber die try-finally-Blöcke nicht vergesen, weil dann gibt´s auch kein OnError mehr, sondern Exceptions. :idea:

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.

Für diesen Beitrag haben gedankt: FinnO, IhopeonlyReader
FinnO
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1331
Erhaltene Danke: 123

Mac OSX, Arch
TypeScript (Webstorm), Kotlin, Clojure (IDEA), Golang (VSCode)
BeitragVerfasst: Mi 19.06.13 23:24 
Endlich mal der Experte :) :flehan:
IhopeonlyReader Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 600
Erhaltene Danke: 23


Delphi 7 PE
BeitragVerfasst: Fr 21.06.13 15:41 
user profile iconNarses hat folgendes geschrieben Zum zitierten Posting springen:
Eigenschaft .ClientType auf ctBlocking und gut ist, dann gibt´s auch keine Ereignisse mehr. Dann aber die try-finally-Blöcke nicht vergesen, weil dann gibt´s auch kein OnError mehr, sondern Exceptions. :idea:

das war das was ich suchte (ClientType ctBlocking) DANKE !.. dazu jetzt noch eine frage..
was ist der unterschied zwischen onconnect und dem code NACH dem open im selben try-blcok?

Beispiel:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
//OnConnect
machwas1

//aufruf des TClientSocket (auf CtBlcoking)
try
Derclient.open;
machwas2;
 finally
 if derclient.socket.connected then derclient.close;
 end;

es macht doch jetzt kein unterschied ob ich machwas in onconnect oder nach dem open aufrufe oder?

_________________
Sucht "neueres" Delphi :D
Wer nicht brauch was er hat, brauch auch nicht was er nicht hat!
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19315
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Fr 21.06.13 16:07 
Wenn du den Socket auf blockierend gestellt hast, blockiert der bis die Operation (das Verbinden) abgeschlossen ist. Dann kannst du nach dem Connect auch etwas ausführen, das auf dem Verbindungszustand basiert und diesen prüft.

Hast du den Socket auf nicht blockierend, wartet der nicht, d.h. du kommst in dem Code nach dem Connect evtl. an bevor das Verbinden abgearbeitet ist. Dann ist der Socket da ggf. noch nicht connected. Dann musst du OnConnect nutzen.
IhopeonlyReader Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 600
Erhaltene Danke: 23


Delphi 7 PE
BeitragVerfasst: Fr 21.06.13 23:59 
Ja, ich meinte jetzt speziell bei ctblocking

_________________
Sucht "neueres" Delphi :D
Wer nicht brauch was er hat, brauch auch nicht was er nicht hat!