Op deze website gebruiken we cookies om content en advertenties te personaliseren, om functies voor social media te bieden en om ons websiteverkeer te analyseren. Ook delen we informatie over uw gebruik van onze site met onze partners voor social media, adverteren en analyse. Deze partners kunnen deze gegevens combineren met andere informatie die u aan ze heeft verstrekt of die ze hebben verzameld op basis van uw gebruik van hun services. Meer informatie.

Akkoord

Vraag & Antwoord

Programmeren

[Delphi] vastlopen

None
18 antwoorden
  • 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
  • Bedankt voor je reactie, maar het is nog steeds niet gelukt. Want er moeten meerdere berichten
    egels 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 <>
  • 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…)
  • Kan ook niet, ik probeer het nu met indy. Ik heb versie 9 gedownload, maar TString Stream bestaat niet (meer) Ik probeer het dan met ReadStrings, maar dan loopt ie weer vast… Ik probeer nog wel ff verder. Maar, als je nog wat weet… :D



    : - )
  • Jawel hoor! Met ReadStream en WriteStream…
  • [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].
  • [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.
  • Ik heb het nu met h4xX0r's code geprobeerd samen met de Timeoutoptie op 5 msec. en nu werkt het! Bedankt!

    : - )
  • Okeej!!

    Waar gebruik je het eigenlijk voor?
  • [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: ]
  • [die site heb ik helemaal zelf ontworpen :D ]

    Is SS read-only? In welke situatie bedoel je precies (code graag :D )?
    Het is heel simpel hoor, het alleen een kwestie van doorhebben.
  • 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(
  • 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.
  • Wat raar… ik krijg het ook niet voorelkaar… hij zit vast… :D
  • Ik weet niet wat de server doet met wat ik stuur, maar ik hoor direct iets terug te krijgen…

    Heeft TIdTCPClient trouwens zoiets als OnRead, of OnReceiveData? Misschien dat het OnWorkBegin of OnWork is, maar ik weet niet hoe die werken.

    : - )
  • 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.
  • [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]

Beantwoord deze vraag

Dit is een gearchiveerde pagina. Antwoorden is niet meer mogelijk.