views:

1144

answers:

2

If I create a TcpChannel using port zero i.e. allowing .Net Remoting to allocate an available port, is there anyway to then determine which port number has been allocated?

I know that I can specify the port number when creating the channel, however I don't want to do this as I want to run multiple instances of the listening application on the same Citrix server - each instance listening on a different port.

Ideally I don't want to have to go to the trouble of reserving a bunch of ports and then keeping track of which ones have been allocated. I'd just like to let the port be allocated automatically - but then I need to be able to know which port number has been allocated.

+2  A: 

I don't know much about this, but browsing at MSDN it states that post zero usage returns a TcpServerChannel, and a TcpServerChannel has a GetChannelUri() method; does that include the port number? (you might need to parse, via new Uri(s).Port).

Again, complete guess-work. If not, just say ;-p

edit by AakashM to add This is the correct approach. Following

var channel = new TcpChannel(0);

the dynamically-allocated post of the contained server channel can be retrieved with

var channelData = (ChannelDataStore)channel.ChannelData;
var port = new System.Uri(channelData.ChannelUris[0]).Port;

The ugly cast is necessary because the TcpChannel.ChannelData property is typed as object...

Marc Gravell
Looking at the sourcecode for the implementation of TcpServerChannel in Mono, I think you're right. The url is in the form tcp://host:port (seehttp://anonsvn.mono-project.com/viewvc/trunk/mcs/class/System.Runtime.Remoting/System.Runtime.Remoting.Channels.Tcp/TcpServerChannel.cs?annotate=HEAD#l182 )
Stobor
Well in theory that would have worked - except that I was using a TcpChannel as opposed to a TcpServerChannel. I've ended up posting an answer with my solution.
daveywc
Can't see that answer...
Marc Gravell
A: 

My solution was as follows:

  • Use the following code to identify an unused port for each instance of the client application:

    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; }

  • Store the unused port number in the client application.

  • Pass the stored port number to the host application via a command line parameter for use when setting up the TcpChannel and calling Activator.GetObject.

  • Use the stored port number in the client application in the URL passed to Activator.GetObject.

daveywc