sto facendo delle prove con un TCP server
dopo aver guardato un po' in giro, ho voluto provare il codice che si trova in questo indirizzo
http://pascalgeek.blogspot.it/2012/06/encryption-decryption-and-asynchronous.html (http://pascalgeek.blogspot.it/2012/06/encryption-decryption-and-asynchronous.html)
Il codice nel blog non prevede che il server restituisca dei dati al client mentre io avrei bisogno di una comunicazione bidirezionale.
Ho voluto simulare che il server, ogni tanto, perdesse del tempo per dei calcoli (ecco il perché di: if (i>0) and ((i mod 3)=0) then sleep(1000) ) per poi tornare a restituire dati al client.
Alla fine il mio client funziona, quello che non mi convince è che ho dovuto implementare una sorta di attesa nel client usando "sleep" (vedere try..except). Non vorrei essere fuori strada...
qualche idea?
ho apportato alcune modifiche per fare le prove, il codice che ho scritto io è tra i "tag" nomorelogic e nomorelogic.end
in particolare ecco il server TCP
program testserver;
{$mode objfpc}{$H+}
uses
{ 1 }
{$ifdef unix}cthreads,{$endif}
Classes,SysUtils,Sockets,fpAsync,fpSock;
type
{ 2 }
TClientHandlerThread = class(TThread)
private
FClientStream: TSocketStream;
public
constructor Create(AClientStream: TSocketStream);
procedure Execute; override;
end;
{ 3 }
TTestServer = class(TTCPServer)
private
procedure TestOnConnect(Sender: TConnectionBasedSocket; AStream: TSocketStream);
public
constructor Create(AOwner: TComponent); override;
end;
{ 4 }
function AddrToString(Addr: TSockAddr): String;
begin
Result := NetAddrToStr(Addr.sin_addr) + ':' + IntToStr(Addr.sin_port);
end;
{ TClientHandlerThread }
{ 5 }
constructor TClientHandlerThread.Create(AClientStream: TSocketStream);
begin
inherited Create(false);
FreeOnTerminate := true;
FClientStream := AClientStream;
end;
{ 6 }
procedure TClientHandlerThread.Execute;
var
Msg : String;
Done: Boolean;
i: integer;
begin
Done := false;
repeat
try
Msg := FClientStream.ReadAnsiString;
WriteLn(AddrToString(FClientStream.PeerAddress) + ': ' + Msg);
// nomorelogic
Writeln('send response');
// following strings
FClientStream.WriteWord(10);
for i:=0 to 9 do begin
FClientStream.WriteAnsiString(IntToStr(i));
if (i>0) and ((i mod 3)=0) then
sleep(1000);
//sleep(250);
end;
//sleep(2000);
//writeln('stop waiting');
Done:=true;
// nomorelogic.end
except
on e: EStreamError do begin
Done := true;
end;
end;
until Done;
WriteLn(AddrToString(FClientStream.PeerAddress) + ' disconnected');
end;
{ TTestServer }
{ 7 }
procedure TTestServer.TestOnConnect(Sender: TConnectionBasedSocket; AStream: TSocketStream);
begin
WriteLn('Incoming connection from ' + AddrToString(AStream.PeerAddress));
TClientHandlerThread.Create(AStream);
end;
{ 8 }
constructor TTestServer.Create(AOwner: TComponent);
begin
inherited;
OnConnect := @TestOnConnect;
end;
{ main }
{ 9 }
var
ServerEventLoop: TEventLoop;
begin
ServerEventLoop := TEventLoop.Create;
with TTestServer.Create(nil) do begin
EventLoop := ServerEventLoop;
Port := 5050;
WriteLn('Serving...');
Active := true;
EventLoop.Run;
end;
ServerEventLoop.Free;
end.
e poi il client
program testclient;
{$mode objfpc}{$H+}
uses
Classes,SysUtils,Sockets,fpAsync,fpSock;
var
ClientEventLoop: TEventLoop;
Response:string;
Done: boolean;
i, scan, err: word;
begin
ClientEventLoop := TEventLoop.Create;
with TTCPClient.Create(nil) do begin
EventLoop := ClientEventLoop;
Host := '127.0.0.1';
Port := 5050;
Active := true;
EventLoop.Run;
Stream.WriteAnsiString('Hello');
sleep(10);
// Response := Stream.ReadAnsiString;
// Writeln(Response);
i:=Stream.ReadWord;
writeln('Follows:', i, ' strings');
scan:=0;
err:=0;
// nomorelogic
Done := false;
repeat
try
Response := Stream.ReadAnsiString;
inc(scan);
WriteLn(Response);
except
on e: EStreamError do begin
inc(err);
sleep(1000);
if err > 3 then
Done := true;
end;
end;
until Done or (i=scan);
// nomorelogic.end
Active := false;
end;
ClientEventLoop.Free;
writeln('disconnected');
end.