簡體   English   中英

C#遠程處理異常:每個套接字地址(協議/網絡地址/端口)通常僅允許使用一種

[英]C# Remoting Exception : Only one usage of each socket address (protocol/network address/port) is normally permitted

我正在使用C#遠程處理來訪問服務器系統上的標簽,並且該標簽的文本將通過在客戶端系統上單擊按鈕來更改。 我在命名RemoteObject的類庫中創建了一個可移動的對象,並將該類庫的引用添加到客戶端和服務器系統,但是在調試服務器系統和客戶端系統時,我得到了一個例外:“每個套接字地址只能使用一種(協議/網絡地址/端口)通常是允許的”

請對此提供幫助,以解決此問題。

RemotableObject.dll

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace RemoteObject
{
    public class Class1 : MarshalByRefObject
    {
        public Class1()
        {
        }

        public void setText()
        {
            ServerClass bs = new ServerClass();
            Label lbl = bs.Controls["label1"] as Label;
            lbl.Text = "New Text";
        }
    }
}

服務器端代碼

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using RemoteObject;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;

namespace Server
{
    public partial class ServerClass : Form
    {
        private Class1 myremoteobject;
        public ServerClass()
        {
            InitializeComponent();
            myremoteobject = new Class1();
            TcpChannel channel = new TcpChannel(30000);
            ChannelServices.RegisterChannel(channel, true);
            RemotingConfiguration.RegisterWellKnownServiceType(typeof(Class1), "CSBU", WellKnownObjectMode.SingleCall);
        }

    }
}

客戶端代碼

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using RemoteObject;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;


namespace Client
{
    public partial class ClientClass : Form
    {
        private Class1 remoteobject = new Class1();
        public ClientClass()
        {
            InitializeComponent();
            TcpChannel chan = new TcpChannel();
            ChannelServices.RegisterChannel(chan,true);
            remoteobject = (Class1)Activator.GetObject(typeof(Class1), "tcp://localhost:30000/CSBU");
        }

        private void changeTextBtn_Click(object sender, EventArgs e)
        {
            remoteobject.setText();
        }
    }
}

請有人幫助我盡快解決此異常。

看來問題在於您的Class1.setText方法創建了一個新的ServerClass 現在,由於創建Class1實例並通過遠程處理使其可用的東西是ServerClass ,這大概意味着到您遠程調用setText方法時,您已經有了ServerClass一個實例,因此結束創造第二個。

這意味着ServerClass構造函數中的所有代碼都運行兩次。 第二次運行時,它將嘗試第二次在端口30000上注冊新的TcpChannel 由於您第一次創建的頻道已在運行,因此您將得到描述的錯誤。

嘗試在ServerClass構造函數上放置一個斷點,我希望您會看到它運行兩次。 第一次您不會收到錯誤,但是第二次您會得到。

解決方案是避免在該setText方法中創建新的ServerClass 如果您的意圖是應該使用遠程調用來修改屏幕上已經存在的表單中的標簽,那么您需要將對現有ServerClass實例的引用傳遞給Class1實例。 (例如,使Class1構造函數將ServerClass作為參數,並將其存儲在字段中。使用它而不是在setText中構造一個新的。)

順便說一句,遠程處理或多或少已被棄用。 目前,WCF是在.NET中進行遠程訪問的常用方法。 要么是Web API。

更新:013/02/12

抱歉,自從我使用Remoting以來已經有一段時間了,因為正如我所提到的, Remoting已過時,您不應該使用它!

因此,我忘記了:遠程處理並不能使注冊一個特定的實例變得很簡單-您注冊了眾所周知的類型,而遠程處理則想為您構造類型。 因此,您需要提出將ServerClass傳遞給Class1其他方法。

例如:

public class Class1 : MarshalByRefObject
{
    public static ServerClass MyServer { get; set; }

    public void setText()
    {
        ServerClass bs = MyServer;
        Label lbl = bs.Controls["label1"] as Label;
        lbl.Text = "New Text";
    }
}

然后您的ServerClass變為:

public partial class ServerClass : Form
{
    public ServerClass()
    {
        InitializeComponent();

        Class1.MyServer = this;

        TcpChannel channel = new TcpChannel(30000);
        ChannelServices.RegisterChannel(channel, true);
        RemotingConfiguration.RegisterWellKnownServiceType(typeof(Class1), "CSBU", WellKnownObjectMode.SingleCall);
    }
}

然后,您將遇到下一個錯誤,即InvalidOperationException ,錯誤為“跨線程操作無效:控制從不是在其上創建線程的線程訪問的'label1'。

這是因為Remoting調用是在輔助線程上進行的,但是您必須僅從其自己的UI線程更新Windows Forms UI元素。

再說一次,請不要使用它,因為正如我之前提到的,不建議使用REMOTE,並且您不應該使用它。 使用WCF,但是對於它的價值,這里是如何處理它:

public void setText()
{
    MyServer.BeginInvoke((Action) setTextOnUiThread);
}

private void setTextOnUiThread()
{
    ServerClass bs = MyServer;
    Label lbl = bs.Controls["label1"] as Label;
    lbl.Text = "New Text";
}

那應該起作用。

再有一次, 不要這樣做-遠程刪除不再是當前的技術。 在WCF INSTEAD上查看

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM