We have a server which we connect with .Net remoting.
The server is on two network, the client is on two network. The client and the server have only one network in common:
Using discovery, we find the IP of the server(in this case: 10.10.10.110). We create the TcpChannel
and we connect to the server.
The server receives the calls, but when it tries to send some information to the client sink. we get an exception saying that we tried to send data to an unreacheable IP(10.12.10.100).
So the server is announcing correctly his address, but how can we indicate to the client to use the network interface with a specific IP?
Some code:
Client side, Initialization:
IDictionary tcpChannelConfiguration = new Hashtable();
string instanceName = "RemotingClient" + Utils.GenerateRandomString(5);
tcpChannelConfiguration["name"] = instanceName);
tcpChannelConfiguration["port"] = 0;
tcpChannelConfiguration["machineName"] = m_interfaceToHost;//This is containing the local interface to use
tcpChannelConfiguration["bindTo"] = m_interfaceToHost;
IClientChannelSinkProvider formatClient = new BinaryClientFormatterSinkProvider(tcpChannelConfiguration, null);
IClientChannelSinkProvider identityFormatClient = new IdentityClientSinkProvider{Next = formatClient};
BinaryServerFormatterSinkProvider formatServer = new BinaryServerFormatterSinkProvider(tcpChannelConfiguration, null)
{TypeFilterLevel = TypeFilterLevel.Full};
m_channel = new TcpChannel(tcpChannelConfiguration, identityFormatClient, formatServer);
ChannelServices.RegisterChannel(m_channel, false);
//Then we get the remote object:
IServer server = (IServer)Activator.GetObject(typeof(IServer), String.Format("tcp://{0}:{1}/{2}", m_ipAddress, m_port, instanceName));
[...]
Here is the exception I'm having server side:
System.Net.Sockets.SocketException (0x80004005): A socket operation was attempted to an unreachable network 10.12.10.100:54330
Server stack trace:
at System.Net.Sockets.Socket.DoConnect(EndPoint endPointSnapshot, SocketAddress socketAddress)
at System.Net.Sockets.Socket.Connect(EndPoint remoteEP)
at System.Runtime.Remoting.Channels.RemoteConnection.CreateNewSocket(EndPoint ipEndPoint)
at System.Runtime.Remoting.Channels.RemoteConnection.CreateNewSocket()
at System.Runtime.Remoting.Channels.RemoteConnection.GetSocket()
at System.Runtime.Remoting.Channels.SocketCache.GetSocket(String machinePortAndSid, Boolean openNew)
at System.Runtime.Remoting.Channels.Tcp.TcpClientTransportSink.SendRequestWithRetry(IMessage msg, ITransportHeaders requestHeaders, Stream requestStream)
at System.Runtime.Remoting.Channels.Tcp.TcpClientTransportSink.ProcessMessage(IMessage msg, ITransportHeaders requestHeaders, Stream requestStream, ITransportHeaders& responseHeaders, Stream& responseStream)
at System.Runtime.Remoting.Channels.BinaryClientFormatterSink.SyncProcessMessage(IMessage msg)
How can I indicate to the client which IP/interface it has to provide to the server?
Is this something we can do by giving a custom ClientSinkProvider
?
Edit
I found something that might be interessting, I noticed that for simple Query-response, the .Net Remoting is working fine, but for some of them, the query gives a object that will be used as callback by the service, and in this case, it is not working.
I just got the source code of .Net to check how this is done, but I didn't found YET the creation of the proxy for the opposite direction.
While having the source code of the TcpChannel, I see that at some point, the method, on the server side(which will establish a connection to the callback on the client) receives the request with the correct remote IP in the header, but ends by having the wrong IP in the URI:
bindTo
setting? msdn.microsoft.com/en-us/library/ms973907.aspx – Unipolarroute print
on the server to get a list of your interfaces and thenroute ADD 10.10.10.100 MASK 255.255.0.0 10.10.0.254 METRIC 3 IF 2
where 10.10.0.254 should be a gateway on your subnet and the 2 after IF should match the number of the interface that corresponds to the IP that is on 10.10.10.110 – UnipolarBonjour
implementation, then decide to connect). There is more than 50 differents clients that will connect to the server, they all have dynamic IP, and we do not master the customer network – CymatiumtcpChannelConfiguration["machineName"] = m_interfaceToHost
and then you usetcpChannelConfiguration
on both, client and server sink provider. Shouldn't each side have some distinct configuration regarding the used network interface and communication endpoint? – PortentBinaryServerFormatterSinkProvider
in the client code, I don't really know how it is affecting the configuration, I only noticed that you initialize it from the same values as theBinaryClientFormatterSinkProvider
. I'm not exactly an expert in this area, so maybe its nothing important. – PortentBinary*FormatterSinkProvider
for both client and server, don't ask me why. – CymatiumTcpClientChannel
if you don't use the server part? Initializing something randomly just to satisfy the parameter list sounds like a bad idea to me (specially when something is not working as it should) – Portent