OK previously I asked about WCF but I had to revert to .Net remoting for a reason that's too long to explain here.

Anyway, everything works well except... I' can't figure out how to disconnect from the client side. Specifically, I'm following the pattern where the server/client shares a common interface declaration, and there is no shared DLL. However on the client side, I have a reference to the interface, but since it isn't derived from MarshalByRefObject, I can't figure out how to initiate a clean disconnect from the client side.

Wrap your code with using block, when leaving the block it'd call dispose on the TcpClient underneath, which will close the connection.

TcpClientChannel doesn't implement interface IDisposable so it can't be used in a using block.

It seems there is no clear way to disconnect explicitly. I think the idea is that the connection will be closed when the lease expires or the client interface instance is GC'ed.

This actually creates a problem for me because due to a complication of the code that the server PInvokes into, the server needs to restart itself between sessions. When this happens and I re-create the interface on the client side using Activator.GetObject, it somehow returns the previous interface instance (probably tries to re-use the previous one due to Singleton) but any calls to it will throw an exception because it isn't connected to the server anymore. I hacked around this problem by putting the code shown above into a loop and if the exception is thrown, try again. It always seems to succeed on the second try.

I'm just thinking there must be a way to close the connection explicitly but I can't figure out how.

I think it's more like connection pooled connections of varies DbConnection implementations (such as SqlConnection). When you call SqlConnection.Close(), the connection is not closed, but just returning to the pool waiting for other threads to use. There aren't explicit way to close a SqlConnection either.

I ran into something similar on a UDP server/client application ages ago. All subsequent UDPClients would continue to use the previous connection. In my case, I think all I had to do was UDPClient.DropMulticastGroup(MyAddress), but TCP is no doubt different.