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:
I wrote a couple of remoting apps years ago, and even though I didn't get this exact error, my understanding is that the server tries to return results by connecting back to the client, but then using the wrong IP.
What happens if you explicitly specify the IP the client shall use for the communication with the server? Try adding the following to your clients .config file:
This should ensure that the connection and traffic is routed through the requested IP - and not by using 10.12.10.100 to connect [this might accually work if that network have some mean to reach 10.11.x.x without passing 10.10.x.x].
Reordering network connection priority helped in my case.
http://ecross.mvps.org/howto/change-network-connection-priority-in-windows-10.htm
We ended by getting the code of the
TcpChannel
and basically, we stored the source IpAddress, that is stored in the headers, and then we replace the URI that we have in theIChannelDataStore
. Also we made sure that the client listen on every address with the same port. Kind of a hack, but it got us out of trouble...