Newsgroup: it.comp.lang.delphi
Titolo: Errore in lettura di un socket client

Salve ragazzi, sono due giorni che ho prb, magari banale, ma non riesco
a trovare una soluzione efficiente.
Dunque ho aperto un socket tra un client delphi e un server scritto in
java!
I due devono comunicare scambiando stringhe; il prb è che quando il
client delphi scrive una stringa al server java va tutto ok, quando
accade il viceversa ho dei prb, prb che cmq riscontro anche aprendo
socket tra client e server delphi.
Questo perche nell'evento OnTimer, il client è sempre in ascolto ma nn
è detto che il server mandi qualcosa, questo ovviamente mi produce il
blocco totale dell'applicazione!Come posso ovviare a cio?
Qualche idea?
Grazie a tutti

 ha scritto nel messaggio 
news:1149171166.1...@f6g2000cwb.googlegroups.com
...

Se mandi le righe relative alla ricezione, forse ti 
si puo' aiutare meglio. A naso forse stai usando il Client


in modalita' bloccante (sincrono) in vece che non 
bloccante. In quest'ultimo modo non ti serve un timer


in quanto il socket ha il suo evento che si attiva 
quando riceve messaggi.


 


Ciao Giorgio




Ciao, uso Indy la pate relativa alla ricezione legata all'evento
OnTimer è:
procedure TForm1.Timer1Timer(Sender: TObject);
var
x:string;
begin
if IdTCPClient.connected  then
begin
x:= IdTCPClient.ReadChar;
ListBox.Items.Add(x)
end;
Grazie

OnTimer č:
Non si usano i timer per le comunicazioni di questo tipo.
Dal client al server si comunica in maniera sincrona e si attende la
risposta in maniera sincrona.  La "recv" di basso livello, usata con i
socket (standard BSD) č per default bloccante.

 socket (standard BSD) è per default bloccante.
Quindi lo devo usare in modalita sincrona o asincrona?
Hai degli esempi da farmi vedere?
Grazie

Quindi lo devo usare in modalita sincrona o asincrona?
Esistono dei metodi specifici per la lettura su TIdTCPClient.
Guarda le demo dei componenti Indy e cerca gli esempi su Google.


Ciao, uso Indy la pate relativa alla ricezione legata all'evento
OnTimer č:


Userei il ClientSocket di Delphi o il Socket del Gruppo ICS di Piette, [...]
Io invece resterei ancorato agli Indy.  Sono senza dubbio i componenti
migliori per la gestione della rete.  Non so perché si voglia rendere
a tutti i costi la comunicazione asincrona, ma in quel caso gestire il
tutto con un evento scatenato da un thread secondario è un'operazione
piuttosto banale...

 ha scritto nel messaggio 
news:m0c082t4212pei13d...@4ax.com...

Il TCP Indy  e' il peggiore componente che ho visto dal momento che non 
permette la scelta Bloccante/Non Bloccante.
La comunicazione asincrona viene eseguita normalmente dai winsocket, basta 
impostare alcune opzioni, e si presta ottimamente
per i sistemi basati sulla programmazione ad eventi.
Giorgio 

sulla programmazione ad eventi.
La libreria di gestione dei socket di Windows è basata sullo standard
BSD, quindi ovviamente consente la creazione di socket non bloccanti e
del relativo meccanismo di polling (man select()) ma non vedo il
motivo di seguire questa strada (vedi sopra).

Andrea Laforgia ha scritto:

Ho fatto questa piccola applicazione secondo voi puo andare?
unit Unit1;
interface
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls,
Forms,
  Dialogs, StdCtrls, ScktComp;
type
  TForm1 = class(TForm)
    ClientSocket: TClientSocket;
    Button1: TButton;
    ListBox1: TListBox;
    Button2: TButton;
    Button3: TButton;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure ClientSocketConnect(Sender: TObject;
      Socket: TCustomWinSocket);
    procedure Button2Click(Sender: TObject);
    procedure ClientSocketDisconnect(Sender: TObject;
      Socket: TCustomWinSocket);
    procedure Button3Click(Sender: TObject);
    procedure ClientSocketRead(Sender: TObject; Socket:
TCustomWinSocket);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
var
  Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
ClientSocket.Port:=7777;
ClientSocket.Host:='localhost';
ClientSocket.Active:=false;
ClientSocket.ClientType:= ctNonBlocking;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
ClientSocket.Active:= true;
end;
procedure TForm1.ClientSocketConnect(Sender: TObject;
  Socket: TCustomWinSocket);
begin
ListBox1.Items.Add('Connesso');
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
ClientSocket.Active:= false;
end;
procedure TForm1.ClientSocketDisconnect(Sender: TObject;
  Socket: TCustomWinSocket);
begin
Listbox1.Items.Add('disconnesso');
end;
procedure TForm1.Button3Click(Sender: TObject);
begin
ClientSocket.Socket.SendText('ciao');
end;
procedure TForm1.ClientSocketRead(Sender: TObject;
  Socket: TCustomWinSocket);
var
x: string;
begin
x:=Socket.ReceiveText;
ListBox1.Items.Add('La stringa ricevuta è: '+x);
end;
end.
Grazie del consiglio

 
......
Nn mi scrive il testo......  :(
dove è che sbaglio?

Grazie del consiglio
Usa i componenti Indy.

Andrea Laforgia ha scritto:

Mi correggo a scrivere scrive ma nn viene letto dal server scritto in
java, mentre prima con Indy lo leggeva solo che mi si bloccava quando
era in ascolto di una risposta

 > Usa i componenti Indy.
Ciao Andrea ho trovato un post scritto da te l'anno scorso mi pare,
dove c'è un client che utlizza thread, io lho adattato al mio esempio
credi che possa andare?
unit Unit1;
interface
uses
   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls,
Forms,
   Dialogs, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient,
   StdCtrls;
type
   TClientThreadErrorNotify = procedure(ASender: TObject; AErrorString:
String) of object;
   TClientThread = class(TThread)
   private
     FError: String;
     FMainFormHandle: HWND;
     FCleanDisconnect: Boolean;
     FOnError: TClientThreadErrorNotify;
     FIdTCPClient: TIdTCPClient;
     procedure SyncException;
   protected
     procedure Execute; override;
     procedure OnThTerminate(ASender: TObject);
   public
     constructor Create; reintroduce; virtual;
     destructor Destroy; override;
     procedure Open(AMainFormHandle: HWND; AHost: String;
APort:Integer;
AResume: Boolean); virtual;
     procedure Close; virtual;
     property OnError: TClientThreadErrorNotify read FOnError write
FOnError;
   end;
type
   TForm1 = class(TForm)
     Memo1: TMemo;
     IdTCPClient1: TIdTCPClient;
     Memo2: TMemo;
     btnDisconnectAll: TButton;
     Button1: TButton;
     procedure FormCreate(Sender: TObject);
     procedure btnDisconnectClick(Sender: TObject);
     procedure Button1Click(Sender: TObject);
     procedure FormDestroy(Sender: TObject);
   private
     FClientThread: TClientThread;
   public
     { Public declarations }
   end;
var
   Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
   IdTCPClient1.Port := 7777;
   IdTCPClient1.Host := 'localhost';
   IdTCPClient1.Connect;
   FClientThread := TClientThread.Create;
   FClientThread.Open(Self.Handle, '127.0.0.1',7777, True);
end;
procedure TForm1.btnDisconnectClick(Sender: TObject);
begin
   IdTCPClient1.Disconnect;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
begin
IdTCPClient1.WriteLn('ciao mamma');
end;
{ TClientThread }
procedure TClientThread.Close;
begin
   FCleanDisconnect := True;
   if not Terminated then
     Terminate;
   if Assigned(FIdTCPClient) then
   begin
     if FIdTCPClient.Connected then
       FIdTCPClient.Disconnect;
   end;
   Free;
end;
constructor TClientThread.Create;
begin
   inherited Create(True);
   FCleanDisconnect := False;
   OnTerminate := OnThTerminate;
end;
destructor TClientThread.Destroy;
begin
   inherited;
end;
procedure TClientThread.Execute;
var
   x:string;
begin
   while not Terminated do
   begin
     if FIdTCPClient.Connected then
     begin
       try
         x:=IdTCPClient1.ReadLn;
       except
         on E:Exception do
           FIdTCPClient.Disconnect;
       end;
     end
     else
     begin
       if not FCleanDisconnect then
       begin
         FError := 'Connection with server lost!';
         Synchronize(SyncException);
       end;
       Terminate;
     end;
   end;
end;
procedure TClientThread.OnThTerminate(ASender: TObject);
begin
   if Assigned(FIdTCPClient) then
   begin
     FIdTCPClient.Free;
     FIdTCPClient := nil;
   end;
end;
procedure TClientThread.Open;
begin
   FMainFormHandle := AMainFormHandle;
   FIdTCPClient := TIdTCPClient.Create(nil);
   FIdTCPClient.Host := AHost;
   FIdTCPClient.Port := APort;
   FIdTCPClient.Connect;
   if AResume then Resume;
end;
procedure TClientThread.SyncException;
begin
   if Assigned(FOnError) then
     FOnError(Self, FError);
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin 
   FClientThread.Free; 
end; 
 
 
end. 
end.

credi che possa andare?
Questo devi dirlo tu... hai provato? funziona?

Andrea Laforgia ha scritto:

Si, nn funziona :)
Cmq  nel tuo esempio vengono aperte due connessioni, nel mio caso ne
devo aprire solo una e nell'execute del thread devo mettere la parte
del codice relativa all ascolto della connessione?

del codice relativa all ascolto della connessione?
Devi fare come illustrato nell'esempio.  Mi spiace, ma visto che hai
un esempio scritto da me di fronte, non riesco a dirti altro...