.Net Remoting: Indicate which local interface to use to connect to one server
Asked Answered
C

3

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

Cymatium answered 19/10, 2015 at 10:55 Comment(19)
Did you try to add a bindTo setting? msdn.microsoft.com/en-us/library/ms973907.aspxUnipolar
@Unipolar yes, but as the spec state: "This attribute can only be used in the server side."Cymatium
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.Unipolar
@Unipolar :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)Cymatium
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.110Unipolar
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.Unipolar
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 networkCymatium
I was already afraid that would be the case.Unipolar
have you tried deactivating the non-required networkinterface on the client and see if the connection then works properly from server to clientCalvincalvina
have you tried ordering of the network interfaces on the the clientside. like blogs.technet.microsoft.com/networking/2015/08/14/…Calvincalvina
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?Portent
@Calvincalvina 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?Cymatium
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.Portent
@Portent Well, the constructor of the TcpChannel require to provide a Binary*FormatterSinkProvider for both client and server, don't ask me why.Cymatium
@Cymatium Well I know why: "The TcpChannel class is a convenience class combining the functionality of the TcpClientChannel class and the TcpServerChannel class". 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)Portent
@Portent You are right, I just tried to use TcpClient and TcpServer, same results :(Cymatium
Actually, since the problem happens when the server sends a response to the client, you could include some server side code in your question.Portent
@Portent 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.Cymatium
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.Bangs
B
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].

Bren answered 14/11, 2016 at 15:13 Comment(10)
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 itCymatium
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: google.se/…Bren
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).Cymatium
Hmm. So the next thing to try is perhaps bumping the channel priority? tcpChannelConfiguration["priority"] = 99;Bren
I will check that(but I've only one channel, so not sure it has influences)Cymatium
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")Bren
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.Bren
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 issueCymatium
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.Bren
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.Cymatium
C
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...

Cymatium answered 21/11, 2016 at 10:58 Comment(0)
H
-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.
Hunley answered 27/6, 2017 at 8:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.