2012-06-07 8 views
6

Mi sto ancora abituando a Indy, essendo un sistema di socket multi-threaded con vaste capacità. Una delle grandi cose che ho visto è come un socket del server può avere un numero di associazioni diverse. Ad esempio, potresti avere 3 collegamenti per 3 porte sullo stesso indirizzo IP. Sto usando Indy 10 su Delphi XE2.Utilizzare i binding multipli del server Indy come socket separati?

sto ri-costruzione di un vecchio sistema di mine che utilizza i vecchio stile TServerSocket e TClientSocket componenti da ScktComps e ri-farlo con Indy TIdTCPServer e TIdTCPClient. Il vecchio sistema in realtà consiste di 3 socket server/client completamente diversi su ciascuna estremità, ogni socket che serve a uno scopo distinto e che lavora insieme - simile a come FTP utilizza un socket per i dati binari e l'altro socket per i comandi.

È possibile simulare tre socket server/client separati all'interno dello stesso componente utilizzando questi binding? Sarebbe bello se potessi dichiarare un solo socket server con 3 porte vincolate, e lo stesso sul client, connesso a 3 porte diverse sul server. Tutto ciò che vorrei fare è eliminare la necessità di creare 3 componenti socket/client client separati e combinarli in uno solo.

risposta

12

Sì, è possibile utilizzare un singolo TIdTCPServer per gestire più porte alla volta. Sul lato client, sono comunque necessari 3 componenti client distinti per connettersi alle diverse porte.

Creare 3 voci nella raccolta TIdTCPServer.Bindings, una per ogni IP/porta locale che si desidera ascoltare, in cui la proprietà TIdSocketHandle.Port corrisponde all'equivoco della proprietà TServerSocket.Port. TServerSocket non supporta nativamente il binding a un IP specifico (sebbene possa essere eseguito con un lavoro manuale), ma la proprietà TIdSocketHandle.IP viene utilizzata a tale scopo, dove una stringa vuota è equiv. A INADDR_ANY.

Nel TIdCPServer.OnConnect, TIdCPServer.OnDisconnect, e TIdCPServer.OnExecute eventi, è possibile utilizzare le proprietà TIdContext.Binding.IP e TIdContext.Binding.Port per differenziare cui collegamento alla presa chiamando è collegato.

Un utilizzo comune di questo è per supportare client SSL e non SSL su porte diverse, ad esempio per protocolli come POP3 e SMTP che supportano SSL/TLS impliciti ed espliciti su porte diverse. TIdHTTPServer esegue questa operazione per supportare gli URL HTTP e HTTPS su un singolo server (è possibile utilizzare TIdHTTPServer.OnQuerySSLPort per personalizzare le porte che utilizzano SSL/TLS anziché no).

Ad esempio:

procedure TForm1.StartButtonCick(Sender: TObject); 
begin 
    IdTCPServer1.Active := False; 
    IdTCPServer1.Bindings.Clear; 

    with IdTCPServer1.Bindings.Add do 
    begin 
    IP := ...; 
    Port := 2000; 
    end; 

    with IdTCPServer1.Bindings.Add do 
    begin 
    IP := ...; 
    Port := 2001; 
    end; 

    with IdTCPServer1.Bindings.Add do 
    begin 
    IP := ...; 
    Port := 2002; 
    end; 

    IdTCPServer1.Active := True; 
end; 

procedure TForm1.IdTCPServer1Execute(AContext: TIdContext); 
begin 
    case AContext.Binding.Port of 
    2000: begin 
     // do something... 
    end; 
    2001: begin 
     // do something else... 
    end; 
    2002: begin 
     // do yet something else ... 
    end; 
    end; 
end; 
+0

Impressionante, chiedo solo è ogni porta utilizzando il suo proprio thread o molto probabilmente tutti e 3 nello stesso thread contesto? –

+1

Ogni voce nella raccolta 'Bindings' viene eseguita nella propria thread accettando le connessioni in entrata sulla rispettiva porta. Ogni connessione client accettata viene quindi eseguita anche nel proprio thread. Quindi se hai 3 voci 'Bindings' e 3 client connessi, cioè 6 thread in esecuzione. –

+0

Perfetto, è esattamente quello che volevo. –