一个remoting做的服务,用一个clinet连接上,没有问题
现在在客户端,用线程跑压力,客户端就出现信道 tcp 已注册的错误
这个错误究竟是说,客户端的tcp信道已注册,还是说服务器端的信道已注册呢
remoting 处理并发的时候,究竟是采用的什么机制,是多线程,还是队列

解决方案 »

  1.   

    我的clinet就是没有固定端口
    TcpChannel chan = new TcpChannel();
    ChannelServices.RegisterChannel(chan);
    Interface.IDALService service = (Interface.IDALService)Activator.GetObject(typeof(Interface.IDALService),"tcp://localhost:9000/GOA Data Access Layer Service");
    string s = service.Test();
      

  2.   

    是的。首先其实不一定需要客户端注册Channel,其实即使注册也不一定需要指定固定的端口号。如果你的程序需要客户端必须这样指定,那么只好放多个物理客户机上去“测试”。
      

  3.   

    这是服务器端的代码
    protected override void OnStart(string[] args)
    {
    // TODO: 在此处添加代码以启动服务。
    //Thread t = new Thread(new ThreadStart(Server.Startup));
    Thread t = new Thread(new ThreadStart(Startup));
    t.Start();
    }
     
    /// <summary>
    /// 停止此服务。
    /// </summary>
    protected override void OnStop()
    {
    // TODO: 在此处添加代码以执行停止服务所需的关闭操作。
    //Server.Stop();
    bRun = false;
    }
    private static bool bRun; public static void Startup()
    {
    TcpChannel channel = new TcpChannel(9000);
    ChannelServices.RegisterChannel(channel);
    RemotingConfiguration.RegisterWellKnownServiceType(typeof(Server),"GOA Data Access Layer Service",WellKnownObjectMode.SingleCall);
    bRun = true;
    while(bRun)
    {
    Thread.Sleep(1000);
    }
    }
      

  4.   

    public class Server:MarshalByRefObject,IDALService
    { public  Server()
    {
    }
    //private static bool bRun;// public static void Stop()
    // {
    // //bRun = false;
    // }
    // #region IDALService 成员
    //
    public string Test()
    {
    return "test";
    }
    //
    // #endregion
    }
    }
      

  5.   

    这是客户端代码
    private void button1_Click(object sender, System.EventArgs e)
    {
    // test();
    // SystemManager.frmSystemSetting setting = new frmSystemSetting();
    // setting.Show();
    Thread []threads = new Thread[40];
    for(int i = 0 ; i < 40 ; i++)
    {
    Thread t= new Thread(new ThreadStart(test));
    threads[i] = t;
    }
    for(int i = 0 ;i <40 ;i++)
    {
    threads[i].Start();
    } }
    private void test()
    {
    TcpChannel chan = new TcpChannel(0);
    ChannelServices.RegisterChannel(chan);
    Interface.IDALService service = (Interface.IDALService)Activator.GetObject(typeof(Interface.IDALService),"tcp://localhost:9000/GOA Data Access Layer Service");
    //Database db = service.GetDatabase();
    //string s = (string)db.ExecuteScalar(System.Data.CommandType.Text , "select messageid from t_message");
    string s = service.Test();
    ChannelServices.UnregisterChannel(chan); }
      

  6.   

    先把 ChannelServices.UnregisterChannel(chan); 注释掉吧!UnregisterChannel 是不可靠的。你应该考虑如何让所有线程在相关的重新分配端口号资源的语句互斥执行。
      

  7.   

    我把问题简化了一下,客户端连接remoting的代码是
    private void test()
    { TcpChannel chan = new TcpChannel();
    ChannelServices.RegisterChannel(chan);
    Interface.IDALService service = (Interface.IDALService)Activator.GetObject(typeof(Interface.IDALService),"tcp://localhost:9000/GOA Data Access Layer Service");
    //Database db = service.GetDatabase();
    //string s = (string)db.ExecuteScalar(System.Data.CommandType.Text , "select messageid from t_message");
    string s = service.Test();
    //ChannelServices.UnregisterChannel(chan); }
    我把线程的并发去了,改成一个顺序的循环
    private void button2_Click(object sender, System.EventArgs e)
    {
    for(int i = 0;i< 40;i++)
    {
    test();
    }
    }
    跟踪这个程序,第一次执行test()没有问题
    当第二次执行test()时
    在Interface.IDALService service = (Interface.IDALService)Activator.GetObject(typeof(Interface.IDALService),"tcp://localhost:9000/GOA Data Access Layer Service");
    中断
    错误就是
    未处理的“System.Runtime.Remoting.RemotingException”类型的异常出现在 mscorlib.dll 中。其他信息: 信道 tcp 已注册。
    如果把//ChannelServices.UnregisterChannel(chan);的注释去掉,就没有问题了
      

  8.   

    这样说,问题很清楚了,就是一个clinet为什么不能向一个server发出两次连接
    问题应该是由于端口已经被占用造成的,但是,为什么不能自动分配端口呢
      

  9.   

    当第二次执行test()时
    ————————————————————————————————
    既然注释掉那句UnregisterChannel,那么第二次执行test必须是新的进程/应用程序域之内。