服务器信道地址是 http://localhost:18001/ETmedia客户端 程序Form1 创建 4个 ClientForm
每个ClientForm都向服务器信道地址是 http://localhost:18001/ETmedia注册第一个注册成功,其它的就会报“信道 'http' 已注册。”(RemotingException) 如何实现一个服务器端server.exe和一个Form1.exe里的多个clientForm向同一个信道注册

解决方案 »

  1.   

    一般情况下用Remoting一个信道就够用
    信道名称在应用程序域中必须是唯一的
    在注册不同信道的时候,显式指定其信道名称
    IChannel channel1 = new TcpClientChannel( "Channel1", new BinaryClientFormatterSinkProvider() ); 
    ChannelServices.RegisterChannel( channel1, true ); 
    IChannel channel2 = new TcpClientChannel( "Channel2", new BinaryClientFormatterSinkProvider() ); 
    ChannelServices.RegisterChannel( channel2, true ); 
    参考
      

  2.   

    客户端代码  private void Form1_Load(object sender, EventArgs e)
            {
                for (int i = 0; i < 2; i++)
                {
                    ETMPlayer xplayer = new ETMPlayer();
                    xplayer.playerid = i;
                    xplayer.Show();
                }
            }using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;
    using System.Threading;
    using ETMedia.Communication;
    using System.Net.Sockets;
    using System.Runtime.Remoting.Channels;
    using System.Runtime.Remoting.Channels.Http;
    using System.Runtime.Remoting;
    using System.Collections;namespace ETMedia.XPlayers
    {
        public partial class ETMPlayer : Form
        {
            public ETMPlayer()
            {
                InitializeComponent();
                     
            }
             public int playerid=0;
            private void ETMPlayer_Load(object sender, EventArgs e)
            {
                MethodInvoker mi = new MethodInvoker(InitializeModule);
                mi.Invoke();
            }
            private void ETMPlayer_FormClosed(object sender, FormClosedEventArgs e)
            {
                if (channel != null)
                {
                    ChannelServices.UnregisterChannel(channel);
                }
                GC.Collect();
            }
            private void buttonSend_Click(object sender, EventArgs e)
            {
                byte[] data = Encoding.Default.GetBytes("你好");
            }
            #region Remoting        HttpChannel channel;        private void InitializeModule()
            {
                //---------------------------------------------------------------------------------------------------
                if (RegisterChannel(10081 , 18001 , "localhost", "ETMPlayer" + playerid))
                {
                    MessageBox.Show("ETMPlayer 已注册到 SERVER", @"成功 ETMPlayer" + playerid);            }
                //---------------------------------------------------------------------------------------------------
            }
            #region  Player Client注册到Agent
            /// <summary>
            ///  Player Client注册到Agent,这里要用一个线程循环注册,如果注册不成功要catch异常,继续直到注册成功
            /// </summary>
            /// <param name="playerport">10081</param>
            /// <param name="agentport">18001</param>
            /// <param name="agentip">localhost</param>
            /// <param name="identifier"> "DMP.Remoting.Agent"</param>
            public bool RegisterChannel(int playerport, int agentport, string agentip, string identifier)
            {
                bool isReg = false;
                while (!isReg)
                {
                    try
                    {
                        // creates a client object that 'lives' here on the client.
                        // this object lives here on the client
                         //_CallbackSink = new CallbackSink();
                        // hook into the event exposed on the Sink object so we can transfer a server 
                        // message through to this class.
                        //_CallbackSink.OnHostToClient += new delCommsInfo(CallbackSink_OnHostToClient);
                         //_CallbackSink.OnAgentToPlayer += new dealInternalMessageInfo(_CallbackSink_OnAgentToPlayer);
                        // Register a client channel so the server can communicate back - it needs a channel
                        // opened for the callback to the CallbackSink object that is anchored on the client!
                                             SoapClientFormatterSinkProvider clientFormatter = new SoapClientFormatterSinkProvider();
                        Hashtable ht = new Hashtable();
                        ht["name"] = identifier;
                        ht["port"] = playerport;                    channel = new HttpChannel(ht, clientFormatter,null);                        
                        ChannelServices.RegisterChannel(channel, false);
                        // now create a transparent proxy to the server component
                        string url= @"http://" + agentip + ":" + agentport + "/" + identifier;
                        RemoteServiceObject obj = (RemoteServiceObject)Activator.GetObject(typeof(RemoteServiceObject), url);
                        //if (obj == null) continue;
                        // Register ourselves to the server with a callback to the client sink.
                        obj.ReceiveFromServer += new DataReceiveHandler(ReceiveFromServerProcess);/////《----------------加了这句就报已被注册了,为什么
                       //_ServerTalk.RegisterAgentToPlayer(dmpPlayer, new dealInternalMessageInfo(_CallbackSink.HandleToPlayer));                    isReg = true;
                    }
                    catch (RemotingException rmt) {
                        isReg = false;
                        System.Diagnostics.Trace.WriteLine(rmt);
                        System.Threading.Thread.Sleep(3000);
                        continue;
                    }
                    catch (SocketException se)
                    {
                        isReg = false;   
                        if (se.SocketErrorCode == SocketError.AddressAlreadyInUse)
                        {
                            System.Diagnostics.Trace.WriteLine(@"Client playerport=" + playerport+"+1");
                            playerport = playerport + 1;
                        }
                        continue;
                    }
                    catch (Exception x)
                    {
                        isReg = false;                  
                        //_CallbackSink = null;
                        //_ServerTalk = null;
                        System.Diagnostics.Trace.WriteLine(x);
                        System.Threading.Thread.Sleep(3000);
                        continue;
                    }
                }
                return isReg;
            }        void ReceiveFromServerProcess(object sender, ReceiveDataEventArgs e)
            {
                MessageBox.Show("ETMPlayer ReceiveFromServerProcess" + e.Data,@"ETMPlayer"+playerid);
            }
            #endregion
            #endregion
        }
    }
      

  3.   

    服务端using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;
    using ETMedia.Communication;
    using System.Threading;
    using System.Runtime.Remoting.Channels;
    using System.Runtime.Remoting.Channels.Http;
    using System.Runtime.Remoting;
    using System.Collections;
    using System.Net.Sockets;namespace ETMedia.Remote
    {
        public partial class FormRemote : Form
        {
            public FormRemote()
            {
                InitializeComponent();
            }        private void FormRemote_Load(object sender, EventArgs e)
            {
                MethodInvoker mi = new MethodInvoker(InitializeModule);
                mi.Invoke();
               
            }
            private void FormRemote_FormClosed(object sender, FormClosedEventArgs e)
            {
                if (http_channel != null)
                {
                    ChannelServices.UnregisterChannel(http_channel);
                }
            }
            //Dictionary <string ,>
              #region Remoting 内部通信的方法        HttpChannel http_channel;        private void InitializeModule()
            {
                //---------------------------------------------------------------------------------------------------            //for (int i = 0; i < 10; i++)
                //{
                //    string name = @"ETMPlayer" + i;
                //    int port = 18001 + i;
                //    if (RegisterChannel(port,name))
                //    {
                //        System.Diagnostics.Trace.WriteLine(name + @"  SERVER注册成功 @" + port);
                //    }
                //}            string name = @"ETMPlayer";
                int port = 18001;
                if (RegisterChannel(port, name))
                {
                    System.Diagnostics.Trace.WriteLine(name + @"  SERVER注册成功 @" + port);
                }
                //---------------------------------------------------------------------------------------------------
            }
            #region 注册服务
            public bool RegisterChannel(int port, string identifier)
            {
                bool isReg = false;
                while (!isReg)
                {
                    try
                    {
                        // Set the TypeFilterLevel to Full since callbacks require additional security requirements                
                        SoapServerFormatterSinkProvider serverFormatter = new SoapServerFormatterSinkProvider();
                        serverFormatter.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;
                        // we have to change the name since we can't have two channels with the same name.
                        Hashtable ht = new Hashtable();
                        ht["name"] = identifier;
                        ht["port"] = port;// 9000;
                        // now create and register our custom HttpChannel 
                         http_channel = new HttpChannel(ht, null, serverFormatter);
                        ChannelServices.RegisterChannel(http_channel, false);
                        //// register a WKO type in Singleton mode          
                        RemotingConfiguration.RegisterWellKnownServiceType(new WellKnownServiceTypeEntry(
                            typeof(RemoteServiceObject),
                            identifier,
                            WellKnownObjectMode.SingleCall   //
                            ));
                        isReg = true;
                    }
                    catch (Exception x)
                    {
                        isReg = false;
                        if (x is SocketException)
                        {
                            SocketException se = (SocketException)x;
                            if (se.SocketErrorCode == SocketError.AddressAlreadyInUse)
                            {
                                System.Diagnostics.Trace.WriteLine(@"Server port=" + port + "+1");
                                port = port + 1;
                            }
                        }
                        System.Threading.Thread.Sleep(3000);
                        continue;
                    }
                }
                return isReg;
            }
            #endregion        #endregion        private void btn_etmply_Play_Click(object sender, EventArgs e)
            {
                byte[] data = Encoding.Default.GetBytes("Play");
     
            }           }
    }
      

  4.   


    //远程对象  
     public delegate void DataReceiveHandler(object sender, ReceiveDataEventArgs e);
        public class RemoteServiceObject : MarshalByRefObject
        {        public RemoteServiceObject() { }
            public event DataReceiveHandler ReceiveFromServer;
            public void OnReceiveFromServer(object sender, ReceiveDataEventArgs e)
            {
                if (this.ReceiveFromServer != null)
                {
                    ReceiveFromServer(this, e);
                }
            }
        }    [Serializable]
        public class ReceiveDataEventArgs : EventArgs
        {
            private string rec_data;        public string Data
            {
                get { return rec_data; }
                set { rec_data = value; }
            }    }
      

  5.   

    我也遇到这个问题了,你可以试试ChannelServices.UnregisterChannel(信道); 我还没有去试过 
    但是我感觉这个错误就是因为你重复注册信道的问题,你可以每次使用完信道后,用ChannelServices.UnregisterChannel注销信道