8

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: enter image description here

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: enter image description here

J4N
  • 19,480
  • 39
  • 187
  • 340
  • Did you try to add a `bindTo` setting? https://msdn.microsoft.com/en-us/library/ms973907.aspx – rene Jan 16 '16 at 20:19
  • @rene yes, but as the spec state: "This attribute can only be used in the server side." – J4N Jan 18 '16 at 10:17
  • Ok, this is maybe a bit of a hack but how about adding a route to the route table on the server to use a specific NIC for that IP? Just for testing to verify that it is only a routing issue. – rene Jan 18 '16 at 10:31
  • @rene :I'm no a professional in networkink, but how would you do that? Is it something that could be done through our .Net application? Do we have to do it for every client?(because we do not know all our clients) – J4N Jan 18 '16 at 14:55
  • You'll have to do a `route print` on the server to get a list of your interfaces and then `route 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 – rene Jan 18 '16 at 15:03
  • If this works, then yes, you'll have to make sure a single route exists to your client. That might involve some network people to add that config... you can have complete subnets on that route setting. – rene Jan 18 '16 at 15:06
  • Well, this is not possible, the server never knows his clients(the clients discovers the servers through a custom `Bonjour` 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 – J4N Jan 18 '16 at 15:33
  • I was already afraid that would be the case. – rene Jan 18 '16 at 15:40
  • have you tried deactivating the non-required networkinterface on the client and see if the connection then works properly from server to client – Jehof Nov 14 '16 at 10:22
  • have you tried ordering of the network interfaces on the the clientside. like https://blogs.technet.microsoft.com/networking/2015/08/14/adjusting-the-network-protocol-bindings-in-windows-10/ – Jehof Nov 14 '16 at 10:25
  • I'm a little confused, since you set `tcpChannelConfiguration["machineName"] = m_interfaceToHost` and then you use `tcpChannelConfiguration` on both, client and server sink provider. Shouldn't each side have some distinct configuration regarding the used network interface and communication endpoint? – grek40 Nov 14 '16 at 12:26
  • @Jehof Disabling other network interfaces on the client usually works(but is not an option). Ordering network interfaces doesn help. I don't understand, I only showed the client side, so how can you now how the server sink provider is working? – J4N Nov 14 '16 at 12:37
  • I only seen your `BinaryServerFormatterSinkProvider` 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 the `BinaryClientFormatterSinkProvider`. I'm not exactly an expert in this area, so maybe its nothing important. – grek40 Nov 14 '16 at 13:00
  • @grek40 Well, the constructor of the TcpChannel require to provide a `Binary*FormatterSinkProvider` for both client and server, don't ask me why. – J4N Nov 14 '16 at 15:05
  • @J4N Well I know why: [*"The TcpChannel class is a convenience class combining the functionality of the TcpClientChannel class and the TcpServerChannel class"*](https://msdn.microsoft.com/en-us/library/system.runtime.remoting.channels.tcp.tcpchannel(v=vs.110).aspx). Maybe use `TcpClientChannel` 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) – grek40 Nov 14 '16 at 15:19
  • @grek40 You are right, I just tried to use TcpClient and TcpServer, same results :( – J4N Nov 15 '16 at 06:18
  • 1
    Actually, since the problem happens when the server sends a response to the client, you could include some server side code in your question. – grek40 Nov 15 '16 at 07:38
  • @grek40 In fact, I did notice that with the if I use the specific client, it doesn't work anymore, the request-reply query work, but when I give a client sink to have a callback, I've no answer. Is this require then? I will add some server side query, but honestly, most of the code is the same as the one for the client. – J4N Nov 15 '16 at 07:55
  • Not sure, but what if you put some TCP/IP socket coding before sending the request to check which server is available and then send the request. – Dirty Developer Nov 21 '16 at 03:40

3 Answers3

1

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:

<configuration>
    <system.runtime.remoting>
        <application>
            <channels>
                <channel ref="tcp" port="0" bindTo="10.10.10.100" />
            </channels>
        </application>
    </system.runtime.remoting>
</configuration>

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].

Fredrik Johansson
  • 3,477
  • 23
  • 37
  • Our configuration is unfortunately in code(not XML), but we tried to set the `bindTo` and the `machineName` to the expected IP, it still doesn't work :( I updated the sample to show how we did it – J4N Nov 14 '16 at 15:58
  • I see. Perhaps you could try to change the NIC order in Windows, to make the system to try using the correct network first? Like so: https://www.google.se/search?q=nic+order+windows&rlz=1CDGOYI_enSE595SE595&hl=en-GB&prmd=ivn&source=lnms&tbm=isch&sa=X&ved=0ahUKEwj52LyF96jQAhUGFiwKHat-BhkQ_AUIBygB&biw=414&bih=660 – Fredrik Johansson Nov 14 '16 at 19:04
  • Yes, we just tried that yesterday, it doesn't help, we got once a success, but then failures again(and reverting this back has the same behavior). – J4N Nov 15 '16 at 06:18
  • Hmm. So the next thing to try is perhaps bumping the channel priority? tcpChannelConfiguration["priority"] = 99; – Fredrik Johansson Nov 15 '16 at 07:47
  • I will check that(but I've only one channel, so not sure it has influences) – J4N Nov 15 '16 at 07:55
  • Another thought: Do you setup the channel similarly on the server (with the same binding/configuration)? And how is the callback performed? Is it just a method i.e. var result = server.SayHello("Bob") – Fredrik Johansson Nov 15 '16 at 08:51
  • Hmm, it also seems that if you specify "machineName" (as you do in your code) that might override "bindTo". Either remove the "machineName" line completely - or set it to e.g. "remotingserver" and "remotingclient" and specify these as mappings to the correct IPs in your c:\windows\system32\drivers\etc\hosts file on both computers. – Fredrik Johansson Nov 15 '16 at 08:57
  • I tried to remove the machineName, now it is working all the time. I tried to add again machineName, working all the time, I cannot reproduce the issue anymore, and I'm quite convinced that it's not a definitive solution to the issue – J4N Nov 15 '16 at 16:00
  • Glad it's working! The indefinite results could be due to cache. Rebooting between tests should take care of clearing & resetting everything and give us more definitive results. – Fredrik Johansson Nov 15 '16 at 16:59
  • No, it doesn't, still the same issue. We found a workaround, by getting the .Net code, we were able to see that the client was providing the wrong IP to the server, and then the server was not able to reach it. So basically we took the TcpChannel implementation, and we changed it to have the correct port. – J4N Nov 21 '16 at 10:02
0

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 the IChannelDataStore. 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...

J4N
  • 19,480
  • 39
  • 187
  • 340
-1

Reordering network connection priority helped in my case.

http://ecross.mvps.org/howto/change-network-connection-priority-in-windows-10.htm

  1. Press the Windows Key + X and select Network Connections from the menu.
  2. Press the ALT key, click Advanced and then Advanced Settings.
  3. Select the network connection and click the arrows to give priority to the network connection.

enter image description here

  1. Click Ok when you are done organizing the priority of the network connection. The computer will now follow an order when connections are available.
Gabriel
  • 377
  • 1
  • 3
  • 15