Autor |
Beitrag |
IhopeonlyReader
      
Beiträge: 600
Erhaltene Danke: 23
Delphi 7 PE
|
Verfasst: 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:
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; ClientT.Port := 123456; ClientT.Open; ClientT.Socket.SendText( '1' ); ClientT.Socket.SendText( 'test' ); 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
Wer nicht brauch was er hat, brauch auch nicht was er nicht hat!
|
|
FinnO
      
Beiträge: 1331
Erhaltene Danke: 123
Mac OSX, Arch
TypeScript (Webstorm), Kotlin, Clojure (IDEA), Golang (VSCode)
|
Verfasst: Di 18.06.13 21:06
Moin,
du hast auch nen Durchsatz...
www.entwickler-ecke....c_60744.html?view=dl
Prost,
|
|
IhopeonlyReader 
      
Beiträge: 600
Erhaltene Danke: 23
Delphi 7 PE
|
Verfasst: Di 18.06.13 21:27
FinnO hat folgendes geschrieben : | du hast auch nen Durchsatz...
|
Tut mir leid, verstehe ich nicht  O:
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
Wer nicht brauch was er hat, brauch auch nicht was er nicht hat!
|
|
FinnO
      
Beiträge: 1331
Erhaltene Danke: 123
Mac OSX, Arch
TypeScript (Webstorm), Kotlin, Clojure (IDEA), Golang (VSCode)
|
Verfasst: Di 18.06.13 21:34
Du musst das Ereignis OnConnect nutzen, ist das, was ich aus Narses' Tutorial mitnehme.
Zitat: | Delphi-Quelltext 1: 2: 3: 4: 5:
| procedure TForm1.ClientSocket1Connect(Sender: TObject; Socket: TCustomWinSocket); begin Log.Lines.Add('Verbunden mit '+ServerAdress.Text); end; | |
|
|
IhopeonlyReader 
      
Beiträge: 600
Erhaltene Danke: 23
Delphi 7 PE
|
Verfasst: Di 18.06.13 22:09
Vielen Dank
So funktionierts
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18:
| procedure TForm1.ClientTOnConnect(Sender: TObject; Socket: TCustomWinSocket); begin ClientT.Socket.SendText( Edit1.Text ); sleep( SizeOf(Edit1.Text) ); ClientT.Close; ClientT.Free; end;
procedure TForm1.Button1Click(Sender: TObject); begin ClientT := TClientSocket.create( nil ); ClientT.Host := 'localhost'; ClientT.Port := 12345; ClientT.OnConnect := ClientTOnConnect; ClientT.Open; end; |
Edit: die Variable muss doch nicht global deklariert werden :freu:
Dazu muss die Procedure zu abgeändert werden:
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) ); 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
Wer nicht brauch was er hat, brauch auch nicht was er nicht hat!
|
|
jaenicke
      
Beiträge: 19315
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: 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 
      
Beiträge: 600
Erhaltene Danke: 23
Delphi 7 PE
|
Verfasst: 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
Wer nicht brauch was er hat, brauch auch nicht was er nicht hat!
|
|
IhopeonlyReader 
      
Beiträge: 600
Erhaltene Danke: 23
Delphi 7 PE
|
Verfasst: 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
Wer nicht brauch was er hat, brauch auch nicht was er nicht hat!
|
|
>M@steR<
      
Beiträge: 288
Erhaltene Danke: 3
|
Verfasst: Mi 19.06.13 16:42
Zuletzt bearbeitet von >M@steR< am Di 17.09.13 03:09, insgesamt 1-mal bearbeitet
|
|
IhopeonlyReader 
      
Beiträge: 600
Erhaltene Danke: 23
Delphi 7 PE
|
Verfasst: Mi 19.06.13 18:25
ok, also muss ich das ganze in ein extra thread einlagern.. schade
_________________ Sucht "neueres" Delphi
Wer nicht brauch was er hat, brauch auch nicht was er nicht hat!
|
|
IhopeonlyReader 
      
Beiträge: 600
Erhaltene Danke: 23
Delphi 7 PE
|
Verfasst: 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:
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; 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; fGeklappt := False; DerClient.Close; DerClient.Free; fFertig := True; end;
constructor TSent.create( IP: String; Port: Word; ZuSendenderText: String ); begin inherited create( true ); fFertig := False; fGeklappt := True; DerClient := TClientSocket.Create( nil ); DerClient.Host := IP; DerClient.Address := IP; DerClient.Port := Port; ZuSenden := ZuSendenderText; DerClient.OnConnect := ClientTOnConnect; DerClient.OnError := ClientTOnError; DerClient.Open; end;
procedure TSent.Execute; begin 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
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 begin Application.ProcessMessages; end; 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
Wer nicht brauch was er hat, brauch auch nicht was er nicht hat!
|
|
jaenicke
      
Beiträge: 19315
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: 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 
      
Beiträge: 600
Erhaltene Danke: 23
Delphi 7 PE
|
Verfasst: 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
Wer nicht brauch was er hat, brauch auch nicht was er nicht hat!
|
|
jaenicke
      
Beiträge: 19315
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: 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 
      
Beiträge: 600
Erhaltene Danke: 23
Delphi 7 PE
|
Verfasst: 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
Wer nicht brauch was er hat, brauch auch nicht was er nicht hat!
|
|
Narses
      

Beiträge: 10183
Erhaltene Danke: 1256
W10ent
TP3 .. D7pro .. D10.2CE
|
Verfasst: Mi 19.06.13 22:53
Moin!
Lieber Gott, was tust du denn da nur immer wieder...  Willst du Reifenhändler werden oder warum erfindest du die Dinger immer wieder neu?!
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.
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
      
Beiträge: 1331
Erhaltene Danke: 123
Mac OSX, Arch
TypeScript (Webstorm), Kotlin, Clojure (IDEA), Golang (VSCode)
|
Verfasst: Mi 19.06.13 23:24
Endlich mal der Experte 
|
|
IhopeonlyReader 
      
Beiträge: 600
Erhaltene Danke: 23
Delphi 7 PE
|
Verfasst: Fr 21.06.13 15:41
Narses hat folgendes geschrieben : | 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.
|
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:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| machwas1
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
Wer nicht brauch was er hat, brauch auch nicht was er nicht hat!
|
|
jaenicke
      
Beiträge: 19315
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: 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 
      
Beiträge: 600
Erhaltene Danke: 23
Delphi 7 PE
|
Verfasst: Fr 21.06.13 23:59
Ja, ich meinte jetzt speziell bei ctblocking
_________________ Sucht "neueres" Delphi
Wer nicht brauch was er hat, brauch auch nicht was er nicht hat!
|
|