Ga naar inhoud

[Delphi] vastlopen


anoniem

Aanbevolen berichten

[color=green:6a23a93ff3]Ik heb een form met een TTcpClient met de naam [i:6a23a93ff3]TCPClient1[/i:6a23a93ff3] en een TListBox met de naam [i:6a23a93ff3]List[/i:6a23a93ff3]. Dan heb ik dit stukje code:[/color:6a23a93ff3] [code:1:6a23a93ff3]While TCPClient1.Receiveln()<>'' do List.AddItem('S: '+TCPClient1.Receiveln(),TCPClient1);[/code:1:6a23a93ff3] [color=green:6a23a93ff3]Maar het programma loopt dan vast, wat is er fout? :( [/color:6a23a93ff3]
Link naar reactie
Dat kan idd niet... Er zijn twee dingen fout: 1. Je gebruikt while, dit is een loop en als deze te lang duurt reageert je programma niet meer. Doe het dan zo: [code:1:08edd945a1] while ... = ... do begin ...; Application.ProcessMessages; end; [/code:1:08edd945a1] Met deze procedure verwerkt het programma alle berichten die Windows gestuurd heeft, gebruik deze liefst altijd in een loop die vaak herhaalt wordt. Doe je dit niet, dan "reageert" het programma niet op de berichten van Windows, de meest voorkomende vorm van vastlopen. 2. Je gebruikt twee keer achterelkaar TCPClient1.ReceiveLn, hij kijkt dus twee keer of er een bericht is. Stel, er komt een bericht: bij while kijktie of er tekst is ontvangen (dat is de eerste keer), vervolgens voert hij het statement uit, hij doet wéér ReceiveLn (dat is de tweede keer). Bij de tweede keer zit er geen bericht meer in, deze heb je immers op de while-regel (de eerste keer) er al uitgehaald! Snappie? Je kan hier twee dingen tegen doen: 1. Laat hem één keer kijken door de ReceiveLn in een variabele te zetten. Bijvoorbeeld: [code:1:08edd945a1] S := TcpClient1.ReceiveLn(); while S <> '' do List.Items.Add(S: '+S); [/code:1:08edd945a1] 2. Gebruik een timer met een interval van 500ms, zo kun je het programma ook andere dingen tussendoor laten doen. Succes, Johan
Link naar reactie
Bedankt voor je reactie, maar het is nog steeds niet gelukt. Want er moeten meerdere berichten/regels ontvangen worden. Kan dat niet met TCPClient? Het kan dacht ik wel met TClientSocket.Socket.ReceiveText, maar die wil ik liever niet gebruiken. Maar als je het op deze manier doet: S := TcpClient1.ReceiveLn(); [b:acb11c460d]while[/b:acb11c460d] S <> [color=darkblue:acb11c460d]''[/color:acb11c460d] [b:acb11c460d]do[/b:acb11c460d] List.Items.Add([color=darkblue:acb11c460d]'S: '[/color:acb11c460d] +S); Kun je het net zo goed met if doen. Maar het is dus de bedoeling dat TcpClient1 blijft ontvangen totdat er niks meer te ontvangen is ([color=darkblue:acb11c460d]''[/color:acb11c460d]) Als jij (of iemand anders natuurlijk) daar een antwoord op weet... graag :-)
Link naar reactie
Uhmm.... Ik gebruik geen TClientSocket/TServerSocket en TTcpClient/TTcpServer (meer). Ik ben overgestapt op Indy (van Nevrona, zie http://www.nevrona.com, het is gratis) en werkt met TStringStream, heel handig. Wat jij wilt moet wel mogelijk zijn denk ik... Misschien dat dit kan?: [code:1:6e23932963] repeat S := TcpClient1.ReceiveLn(); if S <> '' then ListBox.Items.Add(S: "'+S+'"'); Application.ProcessMessages; until S <> ''; [/code:1:6e23932963] (Ik controleer de code overigens niet... misschien typfouten of dat het totaal niet kan...)
Link naar reactie
[quote:5dd79c6388=":-)"]Kan ook niet, ik probeer het nu met indy. Ik heb versie 9 gedownload[/quote:5dd79c6388] [code:1:5dd79c6388] // SERVER - Start server op poort 81 procedure TForm1.ButtonStartServerClick(Sender: TObject); begin IdTCPServer1.DefaultPort := 81; IdTCPServer1.Active := True; end; // SERVER - Dit staat onder de Execute event van IdTCPServer1 procedure TForm1.IdTCPServer1Execute(AThread: TIdPeerThread); begin try AThread.Connection.WriteLn(AThread.Connection.Binding.PeerIP); AThread.Connection.WriteLn('yupz'); AThread.Connection.WriteLn('test'); AThread.Connection.WriteLn('een erg lange string'); AThread.Connection.WriteLn('dit is de vijfde string'); AThread.Connection.WriteLn(''); finally if AThread.Connection.Connected then AThread.Connection.DisconnectSocket; end; end; // CLIENT - Strings van server opvragen procedure TForm1.ButtonHaalDataClick(Sender: TObject); var s: string; begin IdTCPClient1.Host := '127.0.0.1'; IdTCPClient1.Port := 81; IdTCPClient1.Connect; if IdTcpClient1.Connected then try s := ''; repeat s := IdTCPClient1.ReadLn(); if (s <> '') then Memo1.Lines.Add(s); until (s = ''); finally if IdTCPClient1.Connected then IdTCPClient1.DisconnectSocket; end; end; [/code:1:5dd79c6388] Let op, dat [i:5dd79c6388]idTCPClient1.ReadLn[/i:5dd79c6388] de hele applicatie blokkeert totdat er een string wordt ingelezen. Het beste is natuurlijk om dit in een eigen thread uit te laten voeren. Let op, dat een groot deel van de Delphi VCL code niet thread safe is. Dus als je deze gebruikt in de Execute event van idTCPServer1 dan zul je hier dus eventueel rekening mee moeten houden. Bijvoorbeeld door het gebruik van [i:5dd79c6388]Critical Sections[/i:5dd79c6388].
Link naar reactie
[quote:1bc7ba6aac="h4xX0r"]Let op, dat [i:1bc7ba6aac]idTCPClient1.ReadLn[/i:1bc7ba6aac] de hele applicatie blokkeert totdat er een string wordt ingelezen. Het beste is natuurlijk om dit in een eigen thread uit te laten voeren. [/quote:1bc7ba6aac] Dit is niet zo hoor! ReadLn heeft nog twee extra opties, namelijk de Terminator string en de Timeout. Gebruik bijvoorbeeld dit: idTCPClient.ReadLn('', 5), na 5 milliseconde nix stopt hij met kijken, dus niet vastlopen. Dit kan je ook doen: [code:1:1bc7ba6aac] var SS: TStringStream; begin idTCPClient1.Host := '127.0.0.1'; try idTCPClient.Connect; except ShowMessage('Kan geen verbinding maken!'); EXIT; end; SS := TStringStream.Create(''); // SS := TStringStream.Create(Memo1.Text) kan ook SS.DataString := Memo1.Text; try idTCPClient1.WriteStream(SS); finally if idTCPClient1.Connected then idTCPClient1.Disconnect; end; SS.Free; end; [/code:1:1bc7ba6aac] Met een TStringStream dus.
Link naar reactie
[quote:fc4b224536="Johan Stokking"]Okeej!! Waar gebruik je het eigenlijk voor?[/quote:fc4b224536] Voor een nieuwe/eigen versie van msn (ik heb een hekel aan msn, maar iedereen gebruikt het :roll:) p.s. Het is me nu dan toch met Readln gelukt, maar misschien is ReadStream makkelijker. Dus ik ging dat proberen, volgens jouw voorbeeld, maar dan precies anders om, want het moet [i:fc4b224536]Read[/i:fc4b224536]Stream zijn, maar SS is dan read-only... Dus als je me dat nog wil uitleggen?? [b:fc4b224536]: - )[/b:fc4b224536] [Mooie site heb je trouwens... :lol: ]
Link naar reactie
Ik had het verkeerd gedaan, hij is nu niet read-only, maar ik krijg nu een read timeout. Hiermee: [size=10:f29f9e9cd4] [b:f29f9e9cd4]var[/b:f29f9e9cd4] abcd: TStringStream; iets: [b:f29f9e9cd4]String[/b:f29f9e9cd4]; ......... TCP1.WriteLn([color=darkblue:f29f9e9cd4]'Iets voor de server'[/color:f29f9e9cd4]); abcd := TStringStream.Create([color=darkblue:f29f9e9cd4]''[/color:f29f9e9cd4]); TCP1.ReadStream(abcd,[color=darkblue:f29f9e9cd4]-1[/color:f29f9e9cd4],False); Iets:= abcd.DataString [/size:f29f9e9cd4] En niet pas na een tijdje, maar meteen. : - )
Link naar reactie
Wat gebeurt er op de server? Dit? Event onExecute van TidTCPServer: [code:1:f4c406ebef] var OntvangenTekst: String; StringStream: TStringStream; ... OntvangenTekst := AThread.Connection.ReadLn; // Doe iets met OntvangenTekst ... StringStream := TStringStream.Create(Memo1.Text); AThread.Connection.WriteStream(StringStream); StringStream.Free; ... [/code:1:f4c406ebef] In dit geval zou het moeten werken, als hij dus direct iets terugstuurt. Ik ga nu beginnen met een voorbeeldproggoltje voor je... Zet het vanavond nog op Internet.
Link naar reactie
OnWorkBegin is dat er iets gaat gebeuren, je krijgt dan een variabele met hoeveel data er verstuurt/ontvangen gaat worden. Deze moet je dan ff opslaan in een variabele. OnWork is dat er een pakketje verzonden/ontvangen is. De variabele die bij het event zit is hoever hij is ten opzichte van de variabele die je gekregen hebt bij OnWorkBegin, je kan dus een progressbar maken. OnWorkEnd spreekt voorzich, als hij klaar is met versturen/ontvangen. Ik snap het ook niet waarom mijn progje het ook niet doet, altijd als ik met Indy werkt doet hij het wel... Echt vaag.
Link naar reactie
[quote:c2bceba73f=":-)"][quote:c2bceba73f="Johan Stokking"] Waar gebruik je het eigenlijk voor?[/quote:c2bceba73f] Voor een nieuwe/eigen versie van msn (ik heb een hekel aan msn, maar iedereen gebruikt het :roll:) [/quote:c2bceba73f] Heb je de examples al gechecked die bij Delphi worden meegeleverd. Daar zit ook ergens een chat applicatie bij. [quote:c2bceba73f] p.s. Het is me nu dan toch met Readln gelukt, maar misschien is ReadStream makkelijker. Dus ik ging dat proberen, volgens jouw voorbeeld, maar dan precies anders om, want het moet [i:c2bceba73f]Read[/i:c2bceba73f]Stream zijn, maar SS is dan read-only... Dus als je me dat nog wil uitleggen?? [/quote:c2bceba73f] Los van de vraag hoe het een en ander in de praktijk geimplementeerd zou moeten worden en of dit de beste methode is .... [code:1:c2bceba73f] // SERVER - Start server op poort 81 procedure TForm1.ButtonStartServerClick(Sender: TObject); begin IdTCPServer1.DefaultPort := 81; IdTCPServer1.Active := True; end; // SERVER - Dit staat onder de Execute event van IdTCPServer1 procedure TForm1.IdTCPServer1Execute(AThread: TIdPeerThread); begin try AThread.Connection.WriteStrings(MemoSend.Lines); finally if AThread.Connection.Connected then AThread.Connection.DisconnectSocket; end; end; // CLIENT - Strings van server opvragen procedure TForm1.ButtonHaalDataClick(Sender: TObject); var s: string; begin IdTCPClient1.Host := '127.0.0.1'; IdTCPClient1.Port := 81; IdTCPClient1.Connect; if IdTcpClient1.Connected then try repeat Memo1.Lines.Add(IdTCPClient1.ReadLn(EOL,5000)); until (not IdTCPClient1.Connected) finally if IdTCPClient1.Connected then IdTCPClient1.DisconnectSocket; end; end; [/code:1:c2bceba73f]
Link naar reactie

Om een reactie te plaatsen, moet je eerst inloggen

Gast
Reageer op dit topic

×   Geplakt als verrijkte tekst.   Herstel opmaak

  Er zijn maximaal 75 emoji toegestaan.

×   Je link werd automatisch ingevoegd.   Tonen als normale link

×   Je vorige inhoud werd hersteld.   Leeg de tekstverwerker

×   Je kunt afbeeldingen niet direct plakken. Upload of voeg afbeeldingen vanaf een URL in

×
×
  • Nieuwe aanmaken...