Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ensuring that outgoing WCF requests are performed using a specific network interface

I have a remote WCF web service that I'm connecting to from my application.

The application may be running on a server with multiple IP addresses (or multiple physical network interfaces)

I need to make sure that I can control which IP address is being used for the outbound request, instead of just using the 'preferred' interface as per the normal metric rules.

The reason for this is that multiple copies of the software will be running on the same machine, each bound to a specific IP address for its own operations, and the remote service being connected to needs to know which one is being used to connect back to it at a later time (since getting the address wrong means connecting to the wrong service)

With legacy ASMX services this is done by overriding GetWebRequest(Uri uri) on the partial class generated for the service. But I cannot figure out at all how to do this with WCF.

On an unrelated SO post, MVP @JohnSaunders suggested this may be possible by taking over the entire transport mechanism used by WCF. But I've not yet figured out how to do this either.

like image 530
PhonicUK Avatar asked Jul 09 '13 15:07

PhonicUK


1 Answers

This is a tricky problem, which WCF doesn't seem to cater for particularly well.

The only component in the .NET framework that seems to directly deal with the issue of the client address is the ServicePoint class. Specifically, it has a BindIPEndPointDelegate property which lets you control how it selects the client IP. The documentation for the property includes this:

Some load balancing techniques require a client to use a specific local IP address and port number, rather than IPAddress.Any (or IPAddress.IPv6Any for Internet Protocol Version 6) and an ephemeral port. Your BindIPEndPointDelegate can satisfy this requirement.

Thus, you should be able to modify the service point associated with your URL in code like this:

var servicePoint =  ServicePointManager.FindServicePoint(
    new Uri("http://contoso.com/service.svc"));

servicePoint.BindIPEndPointDelegate =
    (sp, remote, retryCount) => new IPEndPoint(address, portNumber);

Obviously this kind of code requires your classes have awareness of the protocol and the endpoint address the client will be communicating with. It would likely be most appropriate to set up this logic as a client behaviour which can be applied to your client channel.

like image 79
Paul Turner Avatar answered Oct 23 '22 04:10

Paul Turner