Newsgroup: it.comp.lang.delphi
Titolo: Info componenti Indy

Salve a tutti.
Non ho mai usato i componenti indy ma, ora, ne ho la necessità (scambio 
informazioni tramite TCP).
Avendo Delphi 2006 e quindi anche i componenti in oggetto versione 10.1 
mi chiedevo se esiste qualche buon tutorial sull'utilizzo di 
quest'ultimi. Cercando in giro ho trovato tutorial ed esempi vecchi che 
poco hanno a che vedere con questa nuova versione (gli esempi in BDS 
2006 poi fanno veramente schifo).
Leggendo la guida e l'help sono riuscito a far comunicare un client con 
un server ma non viceversa, ovvero non riesco ad inviare nulla dal 
server verso un qualsiasi client.
Dove posso andare a vedere? Mi basterebbe anche un esempio funzionante 
ma che usi quest'ultima versione dei componenti Indy.
Grazie a tutti,
David

 un server ma non viceversa [...]
Potrei sbagliarmi, ma implementare il "viceversa" non significa sempre - 
di fatto - far comunicare un client con un server? :-|
Ciao,
   Marco.
-- 
MARCO BREVEGLIERI
  (
http://www.marco.breveglieri.name
)
     Non hai la possibilità di scaricare Turbo Delphi Explorer?
     Te lo spedisco io!! [
http://www.marco.breveglieri.name/?p=48
]

In teoria si ma mi pare una cavolata. Significa che dovrei implementare 
sempre un client ed un server nella medesima applicazione (sia che serva 
solo da client o solo da server).

 server verso un qualsiasi client.
Forse interpreto male la tua domanda...
ti riferisci al fatto che il client non dispone di eventi in ascolto?
V.

server verso un qualsiasi client.
Una volta stabilita la connessione tra client e server, il canale è
bidirezionale.  Metti il client in ascolto con le varie Read*() sulla
connessione.

E fino a qui' tutto ok ma come faccio da server a "parlare" con il client?

No no è che non riesco a trovare le funzioni di invio sul server

E fino a qui' tutto ok ma come faccio da server a "parlare" con il client?
fai una cosa, visto che usi Indy 10 - io il 9 e qualcosa cambia - cerca un 
post in questo stesso ng periodo primi di settembre...l'oggetto è Client 
Server con Indy10 o qualcosa di simile
c'è l'intera unit, dovrebbe schiarirti le idee
Non so se ho capito bene la tua domanda e forse ti sto dicendo una cosa 
scontata...
Comunque, con Indy 9, il concetto sarebbe:
lato client
var
  ServerResponse : string;
begin
  client.connect;
  ServerResponse := client.readln;
  { i comandi sono bloccanti, il client resta in attesa
    fino alla risposta }
  showmessage(ServerResponse);
end;
lato server
già nell'evento OnConnect:
server.WriteLn('welcome');
Ovviamente conviene colloquiare nell'evento OnExecute del Server o con i 
TIdCommand.
Ciao
V

Pare semplice ma dal lato server WriteLn o similari non esistono, in più 
al momento del collegamento di un client non mi ritornano i parametri di 
collegamento dello stesso (IP, Porta, etc...)

 E fino a qui' tutto ok ma come faccio da server a "parlare" con il client?
Scusami ma mi sembra banale: lato server "scrivi" dati sulla connessione
esattamente come li "scrivi" lato client.
-- 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it

 collegamento dello stesso (IP, Porta, etc...)
ah, forse ho capito...
può darsi che tu cerchi di inviare direttamente mezzo server, tipo 
IdTCPServer1.WriteLn...
al contrario devi utilizzare la connessione attiva, ad esempio nell'evento 
OnConnect oppure OnExecute:
AThread.Connection.WriteLn
se usi TIdCommand:
ASender.Thread.Connection.WriteLn
Per ottenere l'IP del client:
var
  IPClient: string
IPClient := [ASender.]AThread.Connection.Socket.Binding.PeerIP - stessa cosa 
per la Porta -
Sbaglio?
V

Grazie sei stato fenomenale.
La dicitura corretta per la versione 10.1 è
AContext.Connection.Socket.Binding.PeerPort
e
AContext.Connection.Socket.Binding.PeerIP
Ora la domanda sorge spontanea come faccio a parlare con questo client? 
Write, WriteLn o altro non sono presenti nel server e, in più la 
proprientà Connection non è accessibile (sembra) a livello di server ( 
TCPServer.ContextClass.Connection)

 TCPServer.ContextClass.Connection)
AContext.Connection.IOHandler.Write
AContext.Connection.IOHandler.WriteLn

certo questo si ma Acontext è disponibile solamente sull'evento 
OnConnect ed Execute quindi non ho la possibilità di inviare qualcosa a 
qualche client in un momento diverso (per caso dovrei memorizzarmi i 
vari Acontext? O c'e' un modo diverso)

"Microges" <microges_No@Spam_email.it> ha scritto nel messaggio 
news:ekjlho$sh8$1...@newsreader.mailgate.org...

in pratica ogni volta che devi inviare qualcosa al client o leggere dati 
relativi ad esso - dimenticati il TCPServer - lo agganci con AContext che 
equivale al mio AThread 

Come ho detto a Giotto Acontext è disponibile solamente sull'evento 



Io personalmente li memorizzo, dovrebbe comunque essere possibile 
accedere a IndyServer.Contexts.LockList,
ricordati di chamare IndyServer.Contexts.UnlockList

"Microges" <microges_No@Spam_email.it> ha scritto nel messaggio 
news:ekjme4$thc$1...@newsreader.mailgate.org...

se lavori con un solo client e puoi mantenere la connessione sempre attiva 
potresti creare un thread - che ti fornisce del metodo Execute - con un 
client sempre in ascolto...
in questo modo, lato server, anche nella procedura di un semplice TButton 
puoi mandare dati al client in ascolto senza usare AContext
ho le unit di Andrea che svolgono questo lavoro ma sono per Indy9
Se gli vuoi dare un'occhiata te le passo 

Siete dei grandi. Ora comincio a capirci qualcosa di più. Mi sono 
rimaste solo due cosucce.
1)
Dal server nella procedura execute utilizzo:
If AContext.Connection.IOHandler.RecvBufferSize > 1 Then
begin
   S := Trim(AContext.Connection.IOHandler.ReadLn);
   .. faccio le mie operazioni e poi ..
   AContext.Connection.IOHandler.WriteLn(Risposta);  // o similari
end
Dal client, dato che non ha un evento execute e quindi uso un timer:
procedure TClient.Timer1Timer(Sender: TObject);
Var
   S : String;
begin
   If Not IdTCPClient1.IOHandler.InputBufferIsEmpty Then
      Begin
        S := Trim(IdTCPClient1.IOHandler.ReadLn);
        ... e qui' faccio le mie operazioni ...
      End;
end;
Il problema è che IdTCPClient1.IOHandler.InputBufferIsEmpty torna sempre 
False e se inserisco lo stesso controllo usato nel server (ovvero 
AContext.Connection.IOHandler.RecvBufferSize > 1) mi ritorna sempre True 
e la lettura successiva si pianta.
Dove sbaglio?
2) Quando chiudo il server (Acrive := False) non riesco subito a farlo 
ripartire - mi occorrono dai 5 ai 30 secondi - e mi ritorna un 
eccezione. Perchè? Ho provato anche a ridurre TerminateWaitTime ma non 
cambia nulla.

 Perchè? Ho provato anche a ridurre TerminateWaitTime ma non cambia nulla.
la butto li di nuovo: magari c'è qualche connessione attiva, o il server sta 
lavorando
potresti creare una nuova applicazione e trascinarci un 
TIdTCPServer...attivarlo e disattivarlo senza codice aggiunto...se l'azione 
è immediata hai conferma che qualcosa del tuo codice interagisce con la 
chiusura
Ciao
V.

 la butto li di nuovo: magari c'è qualche connessione attiva, {..}
Si avevi ragione. Risolto (almeno questo si)

 risultato negativo
quando io mi trovo davanti a questi intoppi riduco il codice all'essenziale 
tanto per verificare che la struttura portante sia corretta
tu dici che il client non riceve nulla...ma questo sempre o solo nel caso in 
questione?
intendo dire, se momentaneamente elimini il timer e ti limiti a ad eseguire 
i punti dal 1 al 4 del mio post precedente il client riceve regolarmente?

No la chiamata a ReadLn si pianta

 No la chiamata a ReadLn si pianta
Scusami se insisto, ma te lo dico perchè io ho ricominciato da zero 3/4 
volte prima di procedere più speditamente
da quel che ho capito non hai ancora avuto il piacere di leggere in un 
client la risposta del server...
io farei (ho fatto) così;
metto da parte il mio progetto e creo due nuove applicazioni, una con il 
server, una con il client.
setto il minimo indispensabile (ip, porte ecc)
nell'OnConnect del server un bel writeln al client
nel client, subito dopo il connect, un bel Risposta := client.readln;
memo1.lines.add(risposta);
nessun controllo, nessuna lettura di buffer...
se la risposta arriva (come dovrebbe) parti con le aggiunte e sicuramente 
scopri dov'è l'errore
Lo so che sembra un procedimento da quinta elementare però garantisco, 
funziona
:-)
V

Server:
procedure TForm6.TCPServerExecute(AContext: TIdContext);
Var
   S : String;
begin
   If Not AContext.Connection.IOHandler.InputBufferIsEmpty Then
      begin
        S := Trim(AContext.Connection.IOHandler.ReadLn);
        Memo1.Lines.Add('Server :"'+S+'"');
        AContext.Connection.IOHandler.WriteLn('Due');
      End;
end;
Sul Client:
IdTCPClient1.Connect;
IdTCPClient1.IOHandler.Writeln('Uno');
Memo1.Lines.Add('Client :"'+IdTCPClient1.IOHandler.ReadLn+'"');
Piu' semplice di cosi'... comunque non funziona, ovvero sul server 
arriva il messaggio ma sul client nulla

"Microges" <microges_No@Spam_email.it> ha scritto nel messaggio
mi togli una semplice curiosità?
mi commenti per favore *If Not 
AContext.Connection.IOHandler.InputBufferIsEmpty Then*

Fatto e non funziona lo stesso.
La chiamata lo inserita solamente per un controllo in più (lo so che è 
inutile)

 Fatto e non funziona lo stesso.
una domanda:
a livello test stai lavorando sulla stessa form?
lo chiedo perchè ho provato il tuo codice sul mio D2006 quindi con la tua 
stessa versione e ho riscontrato problemi nella comunicazione tra client e 
server
quindi ho aperto due sessioni contemporanee di delphi ed ho lanciato le due 
applicazioni (nota, una salvala e rinomina il nome del progetto altrimenti 
non parte)
in questo modo tutto ok!
fammi sapere
V

Grazie della "dritta" era proprio questo. Vallo a capire perchè poi. Bho?

 Grazie della "dritta" era proprio questo. Vallo a capire perchè poi. Bho?
Ri-Bho!
Avendo vari PC in rete il TIdTCPServer mi offriva anche il 192.168.xxx.xxx 
oltre al 127.0.0.1 - ho voluto provare anche quello ma nisba! I due 
componenti sulla stessa form non sono graditi.
Su D7 con Indy9 al contrario nessun problema
Sono quegli intoppi che ti fanno impazzire e perdere ORE di tempo 
inutilmente...
Mah!
Se qualcuno che legge ha qualche idea non esiti...non credo sia molto comodo 
lavorare con due sessioni di Delphi...
Se non lo hai già fatto prova a vedere se cambia qualcosa ponendo i due 
componenti su due form diverse ma nella stessa applicazione...chissà
Ciao
V.

Vabbè fa nulla tanto devono essere 2 applicazioni distinte.
Comunque vorrei ringraziarti per il tempo perso a cercare di risolvermi 
i problemi. Ce ne fossero di più come te (purtroppo le risposte più 
comuni sono "Studia" oppure "Cerca in giro").
Grazie ancora,
David