Newsgroup: it.comp.lang.delphi
Titolo: Passaggio da una porta all'altra

Salve ragazzi,
sto tentando di deviare un flusso di dati entranti da una porta su un
altra porta a quale è connesso un'altro client,in una applicazione
server, usando Indy...
Nell'evento OnExcute del server come una volta che individuo da quale
porta entra il flusso come faccio a farlodeviare sull'altra porta???
Con
AThread.Connection.Socket.Binding.Port = 1050
cambio il settaggio di quella porta e nn e quello il mio scopo!!
Ovviamente devo fare anche il viceversa, cioe quello che entra dalla
porta 2 deve uscire dalla porta1!!
Qualche idea!
Chiedo scusa se magari e banale, e se una cosa del genere lho postata
qualche giorno fa, ma come si puo ben vedere nn sono un super esperto,
ma questa cosa mi serve entro lunedi senno nn faccio una bella fine!!:D

 porta entra il flusso come faccio a farlodeviare sull'altra porta???
Mi pareva di averti già suggerito come fare.  Non puoi cambiare porta in 
quel modo e non è ciò che ti serve fare.  Tu hai due client connessi su 
due porte diverse e una volta connessi al server tu puoi memorizzare, da 
qualche parte le loro connessioni.  Da quel punto in poi, qualsiasi cosa 
arriva da un client (leggere) lo puoi indirizzare all'altro client 
(scrivere) discriminando se leggere o scrivere in base alla porta su cui 
sono connessi.
Il codice del server:
unit Unit1;
interface
uses
   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, 
Forms,
   Dialogs, IdBaseComponent, IdComponent, IdTCPServer, StdCtrls;
type
   TForm1 = class(TForm)
     Button1: TButton;
     IdTCPServer1: TIdTCPServer;
     Memo1: TMemo;
     procedure FormCreate(Sender: TObject);
     procedure FormDestroy(Sender: TObject);
     procedure IdTCPServer1Execute(AThread: TIdPeerThread);
     procedure IdTCPServer1Connect(AThread: TIdPeerThread);
     procedure IdTCPServer1Disconnect(AThread: TIdPeerThread);
   private
     FOutputThread: TIdPeerThread;
   public
   end;
var
   Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
   FOutputThread := nil;
   IdTCPServer1.Bindings.Add.Port := 55555; // porta con connessioni in 
entrata
   IdTCPServer1.Bindings.Add.Port := 55556; // porta con connessioni in 
uscita
   IdTCPServer1.Active := True;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
   IdTCPServer1.Active := False;
end;
procedure TForm1.IdTCPServer1Execute(AThread: TIdPeerThread);
var
   DataSize: Cardinal;
   DataStream: TMemoryStream;
begin
   try
     if Assigned(AThread) and AThread.Connection.Connected then
     begin
       if AThread.Connection.Socket.Binding.Port = 55556 then
         Sleep(100) // ignoriamo qualsiasi cosa arrivi dalla porta 55556
       else
       begin
         DataSize := AThread.Connection.ReadCardinal;
         Memo1.Lines.Add(Format('DataSize read: %d', [DataSize]));
         if DataSize>0 then
         begin
           DataStream := TMemoryStream.Create;
           try
             AThread.Connection.ReadStream(DataStream, DataSize);
             if Assigned(FOutputThread) and 
FOutputThread.Connection.Connected then
             begin
               FOutputThread.Connection.WriteCardinal(DataSize);
               DataStream.Position := 0;
               FOutputThread.Connection.WriteStream(DataStream);
             end;
           finally
             DataStream.Free;
           end;
         end;
       end;
     end;
   except
     on E: Exception do
     begin
       Application.MessageBox(PChar(Format('%s.%s(): %s', [ClassName, 
'IdTCPServer1Execute', E.Message])),
                              'Attenzione', MB_ICONWARNING+MB_OK);
       if Assigned(AThread) then
         AThread.Connection.Disconnect;
       if Assigned(FOutputThread) then
       begin
         FOutputThread.Connection.Disconnect;
         FOutputThread := nil;
       end;
     end;
   end;
end;
procedure TForm1.IdTCPServer1Connect(AThread: TIdPeerThread);
begin
   Memo1.Lines.Add(Format('client connected on port: %d', 
[AThread.Connection.Socket.Binding.Port]));
   if AThread.Connection.Socket.Binding.Port = 55556 then
   begin
     if Assigned(FOutputThread) then AThread.Connection.Disconnect
     else
       FOutputThread := AThread;
   end;
end;
procedure TForm1.IdTCPServer1Disconnect(AThread: TIdPeerThread);
begin
   Memo1.Lines.Add(Format('client disconnected on port: %d', 
[AThread.Connection.Socket.Binding.Port]));
   if AThread = FOutputThread then
     FOutputThread := nil;
end;
Il codice del client:
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;
     function GetHost: string;
     procedure SyncException;
   protected
     procedure Execute; override;
     procedure Operation(AStream: TStream); virtual;
     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;
     property Host:String read GetHost;
   end;
type
   TForm1 = class(TForm)
     Memo1: TMemo;
     IdTCPClient1: TIdTCPClient;
     Memo2: TMemo;
     btnDisconnectAll: TButton;
     Button1: TButton;
     procedure FormCreate(Sender: TObject);
     procedure ClientConnectedEvent(Sender: TObject);
     procedure ClientDisconnectedEvent(Sender: TObject);
     procedure btnDisconnectAllClick(Sender: TObject);
     procedure Button1Click(Sender: TObject);
     procedure FormDestroy(Sender: TObject);
     procedure WMStartReceivedData(var Msg: TMessage); message WM_USER+100;
     procedure WMWriteReceivedData(var Msg: TMessage); message WM_USER+101;
     procedure WMEndReceivedData(var Msg: TMessage); message WM_USER+102;
   private
     FClientThread: TClientThread;
   public
     { Public declarations }
   end;
var
   Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.ClientConnectedEvent(Sender: TObject);
begin
   TMemo((Sender as TIdTCPClient).Tag).Lines.Add('Connesso!');
end;
procedure TForm1.ClientDisconnectedEvent(Sender: TObject);
begin
   TMemo((Sender as TIdTCPClient).Tag).Lines.Add('Disconnesso!');
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
   Randomize;
   IdTCPClient1.Port := 55555;
   IdTCPClient1.Host := '127.0.0.1';
   IdTCPClient1.Tag := Integer(Memo1);
   IdTCPClient1.Connect;
   FClientThread := TClientThread.Create;
   FClientThread.Open(Self.Handle, '127.0.0.1', 55556, True);
end;
procedure TForm1.btnDisconnectAllClick(Sender: TObject);
begin
   IdTCPClient1.Disconnect;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
   I, N, Num: Cardinal;
   DataSize: Cardinal;
   DataStream: TMemoryStream;
begin
   N := Random(5)+1;
   DataSize := N * Sizeof(N);
   DataStream := TMemoryStream.Create;
   try
     IdTCPClient1.WriteCardinal(DataSize);
     Memo1.Lines.Add('Stream data written: ---- start');
     for I := 1 to N do
     begin
       Num := Random(2000)+100;
       Memo1.Lines.Add(IntToStr(Num));
       DataStream.WriteBuffer(Num, SizeOf(Num));
     end;
     Memo1.Lines.Add('Stream data written: ---- end');
     IdTCPClient1.WriteStream(DataStream);
   finally
     DataStream.Free;
   end;
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
   DataSize: Cardinal;
   DataStream: TMemoryStream;
begin
   while not Terminated do
   begin
     if FIdTCPClient.Connected then
     begin
       try
         DataSize := FIdTCPClient.ReadCardinal;
         DataStream := TMemoryStream.Create;
         try
           if DataSize>0 then
             FIdTCPClient.ReadStream(DataStream, DataSize);
           Operation(DataStream);
         finally
           DataStream.Free;
         end;
       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;
function TClientThread.GetHost: string;
begin
   Result := FIdTCPClient.Host;
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 TClientThread.Operation;
var
   N: Cardinal;
begin
   PostMessage(FMainFormHandle, WM_USER+100, N, 0);
   AStream.Position := 0;
   while AStream.Read(N, SizeOf(N))>0 do
     PostMessage(FMainFormHandle, WM_USER+101, N, 0);
   PostMessage(FMainFormHandle, WM_USER+102, N, 0);
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
   FClientThread.Free;
end;
procedure TForm1.WMEndReceivedData(var Msg: TMessage);
begin
   Memo2.Lines.Add('Stream data read: ---- start');
end;
procedure TForm1.WMStartReceivedData(var Msg: TMessage);
begin
   Memo2.Lines.Add('Stream data read: ---- end');
end;
procedure TForm1.WMWriteReceivedData(var Msg: TMessage);
begin
   Memo2.Lines.Add(IntToStr(Msg.WParam));
end;
end.
end.

 procedure TForm1.WMStartReceivedData(var Msg: TMessage);
Il codice di queste due è invertito.
La fretta ;-)

Nn so davvero come ringraziarti sei stato molto gentile, lo provo
domani mattina, perche sono stanco. grazie ancora!

Ciao Andrea ho provato adesso il tuo codice!
Funziona!! Ma si puo realizzare una cosa simile in maniera piu
semplice? Mi spiego meglio, io lavoro su delphi da un paio di mesi, e
come vedi nn ho molto le idee chiare.
Cmq ho tirato su una sorte di applicazioni che che fa streaming video,
dove chi manda video fa da server e chi riceve fa da client!!!
Ora io devo rendere il server un altro client e creare un server di
relay intermedio che prenda il flusso su una porta e lo renda
disponibile sull'altra e viceversa!! Io ho chiesto suggerimenti per
fare un applicazione del genere per capire il modello ma cosi mi si
stravolege il mondo, e a questo punto nn so se si possa fare!!! Se hai
tempo ti posso mandare su email il codice e mi puoi dire se cho
speranza di risolvere,senno manco ci perdo tempo!!! Dimmi te! Grazie
intanto

 semplice? 
Piů semplice di quello che ti ho fatto vedere? Non credo proprio.

 stravolege il mondo
Aggiungo solo una cosa (senza cattiveria): ti si stravolge il mondo 
perché evidentemente non hai conoscenze sufficienti per scrivere 
un'applicazione del genere e sopratutto per scriverla in Delphi, visto 
che lo conosci solo da due mesi.  Molti programmatori si buttano in 
progetti al di sopra delle proprie possibilità, convinti di potercela 
fare.  Poi, altri sono costretti a riscrivere le loro applicazioni per 
farle funzionare.  Se vuoi sapere se dovresti rinunciare, per evitare di 
fare brutta figura, per non deludere terribilmente il cliente e per 
evitare che altri riscrivano la tua applicazione in un futuro prossimo, 
la mia personale risposta è sì, rinuncia.

No, infatti nn la prendo con cattiveria, anzi hai ragione, e credimi la
penso come te...
Nn e che mi sono buttato in un applicazione al di sopra di me, ma
purtroppo sono un neolaureato (nn in informatica)  e con voglia di
lavorare e apprendere, e quindi mi si e presentatat questa opportunità
e ci ho provato!! Tutto qua! Io rispetto tutti, e capisco che spesso
gente come me per voi e pesante!! Ma credimi per due mesi che lo
studiando e gia tanto quello che ho creato ed ho piu appreso in questo
gruppo che studiando su manuali!!
Prendero spunto da cio che mi hai inviato!!
Ti ringrazio!

Ciao, nn mi arrendo e quindi ho ripreso in mano l'esempio,  alcune
informazione relative al codice:
1) Posso separare i 2 client, nel senso di vederli su un form apparte?
In questo caso nel nuovo form basta che inserisco solo la nuova classe
TClientThread?
2) Se voglio rendere la cosa bidirezionale cioe che cio che il client 1
manda arriva al client 2 e poi il client 2 risponde e ciò che invia
arriva al client 1 basterebbero alcune modifiche sul codice e dovrei
aggiunge diciamo un'altra variabile FThreadout??

