2010-08-25 20 views
7

Ho un servizio WCF net.tcp e vorrei che il sistema operativo selezionasse la porta su cui doveva essere ascoltato. Quindi ho impostato la porta su 0 nel mio URI, e netstat conferma che il sistema operativo ha scelto una porta nell'intervallo 5000.Come posso ottenere la porta su cui è in ascolto un servizio WCF?

Come posso trovare la porta effettiva che è stata selezionata, in codice, all'interno del processo di servizio?

del codice per mostrare quello che ho provato:

Type serviceType = ...; 
Uri address = new Uri("net.tcp://0.0.0.0:0/Service/"); 
ServiceHost serviceHost = new ServiceHost(serviceType, address); 
ServiceEndpoint endPoint = serviceHost.AddServiceEndpoint(type, binding, ""); 
int port1 = endPoint.ListenUri.Port; // returns 0 
int port2 = serviceHost.BaseAddresses.First().Port; // also returns 0 
+0

È piuttosto raro che un servizio venga ascoltato su una porta a caso: c'è un motivo per cui vuoi farlo? – Cocowalla

+0

@Cocowalla: il servizio fa parte di un processo di lavoro, quindi possono essercene più di una alla volta e stiamo esaminando soluzioni che non implicano la condivisione di porte TCP .NET. – ngoozeff

+0

possibile duplicato di [Come posso ottenere l'indirizzo di ascolto/porta di un servizio WCF?] (Http://stackoverflow.com/questions/2207348/how-can-i-get-the-listening-address-port-of -a-wcf-service) – mafu

risposta

10

Non sono sicuro se questo aiuterà, ma c'è una domanda simile già su SO: How can I get the listening address/port of a WCF service?

La parte rilevante di una risposta sostenuto che si consiglia di provare:

foreach (var channelDispatcher in serviceHost.ChannelDispatchers) 
{ 
      Console.WriteLine(channelDispatcher.Listener.Uri); 
} 

Quindi forse avete bisogno di channelDispatcher.Listener.Uri.Port.

Spero che questo aiuti!

+1

@D Hoerster: sfortunatamente questo restituisce solo l'URI che ho passato. Grazie per il puntatore all'altra domanda. – ngoozeff

+3

@D Hoerster: sembra che abbiamo un vincitore. Ho anche dovuto impostare endPoint.ListenUriMode = ListenUriMode.Unique; per farlo funzionare (e disabilitare la condivisione delle porte sull'associazione). – ngoozeff

+0

Hai chiamato per aprire? – BozoJoe

1

In alternativa, si potrebbe trovare un porto franco per WCF da usare da soli:

private int FindPort() 
{ 
    IPEndPoint endPoint = new IPEndPoint(IPAddress.Any, 0); 

    using (Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)) 
    { 
     socket.Bind(endPoint); 
     IPEndPoint local = (IPEndPoint)socket.LocalEndPoint; 
     return local.Port; 
    } 
} 

Codice da here.

+1

Questo non è sicuro. Qualcun altro può strappare la porta dopo che il socket è stato eliminato ma prima che ServiceHost sia aperto. Quindi questo metodo potrebbe fallire sporadicamente. – BatteryBackupUnit

3

Una volta avviato il servizio, è possibile ottenere una descrizione completa degli endpoint effettivamente creati dalla raccolta Description.Endpoints (ciò non funziona finché non viene chiamato Open()). Da questa raccolta puoi ottenere l'indirizzo. Sfortunatamente devi stringere l'indirizzo per la porta.

Questo è ciò che il mio server registra dopo ogni servizio Open().

 serviceHost.Open(); 

     // Iterate through the endpoints contained in the ServiceDescription 
     System.Text.StringBuilder sb = new System.Text.StringBuilder(string.Format("Active Service Endpoints:{0}", Environment.NewLine), 128); 
     foreach (ServiceEndpoint se in serviceHost.Description.Endpoints) 
     { 
      sb.Append(String.Format("Endpoint:{0}", Environment.NewLine)); 
      sb.Append(String.Format("\tAddress: {0}{1}", se.Address, Environment.NewLine)); 
      sb.Append(String.Format("\tBinding: {0}{1}", se.Binding, Environment.NewLine)); 
      sb.Append(String.Format("\tContract: {0}{1}", se.Contract.Name, Environment.NewLine)); 
      foreach (IEndpointBehavior behavior in se.Behaviors) 
      { 
       sb.Append(String.Format("Behavior: {0}{1}", behavior, Environment.NewLine)); 
      } 
     } 

     Console.WriteLine(sb.ToString()); 
+0

+1 per farmi seguire la strada giusta – ngoozeff

Problemi correlati