0
using System;
using System.Collections;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using System.Runtime.Remoting;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.Write("press any key plus enter to create server: ");
            if (Console.ReadLine().Length > 0)
            {
                var serverProv = new BinaryServerFormatterSinkProvider();
                serverProv.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;
                IDictionary props = new Hashtable();
                props["port"] = 17017;
                props["name"] = "tcp server";
                var channel = new TcpChannel(props, null, serverProv);
                ChannelServices.RegisterChannel(channel, false);

                RemotingConfiguration.RegisterWellKnownServiceType(typeof(Server), "server",
                                                                   WellKnownObjectMode.Singleton);
                Console.WriteLine("Server created");
            }
            else
            {
                ChannelServices.RegisterChannel(new TcpChannel(), false);
                Server server = (Server)Activator.GetObject(typeof(Server), "tcp://localhost:17017/server");
                Client client = new Client();
                client.Connect(server);
            }
            Console.ReadLine();
        }
    }

    class Server : MarshalByRefObject
    {
        //private List<Client> cilents = new List<Client>();

        public event EventHandler ClientedAdded;

        public void AddClient(Client client)
        {
            if (ClientedAdded != null)
            {
                foreach (EventHandler handler in ClientedAdded.GetInvocationList())
                {
                    handler.BeginInvoke(this, EventArgs.Empty, null, null);
                }
            }
        }
    }

    class Client : MarshalByRefObject
    {
        public void Connect(Server server)
        {
            server.ClientedAdded += server_ClientedAdded;

            server.AddClient(this);
        }

        void server_ClientedAdded(object sender, EventArgs e)
        {
            Console.WriteLine("server_ClientedAdded");
        }
    }
}

First, run the exe and create a server. Then run the exe and create a client by pressing Enter directly.

The exception will be thrown at handler.BeginInvoke(this, EventArgs.Empty, null, null);.

This remoting proxy has no channel sink which means either the server has no registered server channels that are listening, or this application has no suitable client channel to talk to the server.

So how to fix it?

I found a similar question on http://www.codeguru.com/forum/showthread.php?t=420124. The author provided a solution but it is too brief for me to understand.

Gqqnbig
  • 5,845
  • 10
  • 45
  • 86
  • FYI, I presume you know that Remoting has been deprecated in favor of WCF? – John Saunders Jan 02 '12 at 08:04
  • I know. Remoting is esaier than WCF, I think. Since my application has embraced WPF, I don't want to spend my time on learning both WPF and WCF. – Gqqnbig Jan 02 '12 at 09:04
  • No, WCF is far simpler than remoting. Remoting is kind of dead, but good luck. – John Saunders Jan 02 '12 at 19:13
  • 2
    @John Saunders: Remoting isn't deprecated, it's [legacy](http://stackoverflow.com/questions/1294494/). There's a big difference. – ulatekh Jun 23 '15 at 00:21
  • @ulatekh: and what do you believe the difference to be? In either case, it shouldn't be used for new development. – John Saunders Jun 23 '15 at 00:50
  • @John Saunders: As explained in the link, "deprecated" means it's going away some day, and "legacy" means it won't. Microsoft still supports COM, after all. And it should be used for new development if it's appropriate, e.g. if marshal-by-ref is needed. – ulatekh Jun 24 '15 at 15:52
  • "Legacy" means "don't use it to write new code" and "only the most critical security bugs will be fixed - and no other bugs". – John Saunders Jun 24 '15 at 15:59

2 Answers2

0

I don't know what might be the problem, but 2 days ago I had to code a tiny application using the same technique (TCP Channels)

Here's a piece of the code (it works well, tested many times):

Server:

    TcpChannel chan = new TcpChannel(8086);
    ChannelServices.RegisterChannel(chan);
    RemotingConfiguration.RegisterWellKnownServiceType
    (Type.GetType("ClockBiometric.RequestServer"),
    "checkFingerprintTemplate", WellKnownObjectMode.Singleton);

Client:

RequestServer obj =
                  (RequestServer)Activator.GetObject(typeof(ClockBiometric.RequestServer)
                                                     ,"tcp://localhost:8086/checkFingerprintTemplate");
                if (obj == null)
                    // couldn't reach server
                else obj.checkFingerprintTemplate(1300, "abcd"); // just call some function

And RequestServer class is:

public class RequestServer : MarshalByRefObject
{
    public RequestServer()
    {
    }

    public void checkFingerprintTemplate(int iIndexNum, String sTemplate)
    {
        doSomeStuff();
    }
}

Hope this helps!

Shai
  • 25,159
  • 9
  • 44
  • 67
  • I think the point is that in my code the server calls a method on clients via delegate. That makes the situation different. – Gqqnbig Jan 02 '12 at 07:49
0

I solved it!

Just try using

handler(this, EventArgs.Empty)

rather than

handler.BeginInvoke(this, EventArgs.Empty, null, null); 

I got an exception saying can not call a private method.

Then the problem is clear and I make server_ClientedAdded public.

Now the code works!

Gqqnbig
  • 5,845
  • 10
  • 45
  • 86