首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

.NET Remoting 實戰:按值封送對象至遠端伺服器完整教學

     編輯:關於C語言

概述

.NET Remoting 是 .NET Framework 早期的分布式通訊技術,支援跨應用程式域、跨程序、跨機器的對象調用。本文示範如何建立一個可按值封送的類別庫,並透過 TCP 通道在伺服器端註冊為 WellKnownObjectMode.SingleCall 模式的遠端物件,客戶端透過代理透明調用。

架構圖解

+----------------+       TCP 7777       +----------------+
|  Client (WinForms)  | <----------------> |  Server (WinForms)  |
|  引用 DLL.dll      |   遠端代理調用      |  託管 api 物件      |
+----------------+                      +----------------+
           ^                                      ^
           | 共用介面/類型定義 (DLL.dll)          |
           +--------------------------------------+

步驟 1:建立共用類別庫專案

專案結構

  • DLL.dll:包含可序列化的資料實體 test 及繼承 MarshalByRefObject 的遠端服務類別 api。

核心代碼

// test.cs - 按值封送的資料物件(需 [Serializable])
using System;

namespace DLL
{
    [Serializable]
    public class test
    {
        public test() { }
        public string Time => DateTime.Now.ToString();
    }
}

// api.cs - 遠端服務物件(繼承 MarshalByRefObject,按引用封送)
using System;
using System.IO;

namespace DLL
{
    public class api : MarshalByRefObject
    {
        public api() { }

        public string GetTime() => new test().Time;

        public string[] GetDirectorIEs(string path) => Directory.GetDirectories(path);

        public string[] GetFiles(string path) => Directory.GetFiles(path);
    }
}

關鍵點:

  • test 標記 [Serializable],跨界傳遞時會被「按值封送」(序列化副本傳至客戶端)。
  • api 繼承 MarshalByRefObject,跨界傳遞的是「透明代理」,實際調用在伺服器端執行(按引用封送)。

步驟 2:建立伺服器端應用程式

通道註冊與服務發布

using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using DLL;

namespace Server
{
    public class Form1 : System.Windows.Forms.Form
    {
        private void Form1_Load(object sender, EventArgs e)
        {
            // 1. 建立 TCP 通道監聽埠 7777
            TcpChannel chan = new TcpChannel(7777);
            ChannelServices.RegisterChannel(chan, false);

            // 2. 註冊遠端類型為 SingleCall 模式(每次呼叫新實例)
            RemotingConfiguration.RegisterWellKnownServiceType(
                typeof(DLL.api),   // 服務類型
                "test",            // 服務 URI 片段
                WellKnownObjectMode.SingleCall);
        }
    }
}

步驟 3:建立客戶端應用程式

全域代理取得

using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using DLL;

namespace Client
{
    public static class Global
    {
        public static string Host { get; set; } = "localhost";
        public static int Port { get; set; } = 7777;

        public static DLL.api ApiProxy
        {
            get
            {
                string url = $"tcp://{Host}:{Port}/test";
                return (DLL.api)Activator.GetObject(typeof(DLL.api), url);
            }
        }
    }
}

主程式調用示範

using System;
using System.Windows.Forms;

namespace Client
{
    static class Program
    {
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            // 註冊客戶端通道(無需指定埠,系統自動分配)
            ChannelServices.RegisterChannel(new TcpChannel(), false);

            Application.Run(new Form1());
        }
    }

    public partial class Form1 : Form
    {
        private void Form1_Load(object sender, EventArgs e)
        {
            try
            {
                // 遠端呼叫:取得伺服器 C:\ 目錄下文件列表
                string[] files = Global.ApiProxy.GetFiles(@"C:\");
                // 繫結至 UI 控制項...
            }
            catch (Exception ex)
            {
                MessageBox.Show($"遠端調用失敗:{ex.Message}");
            }
        }
    }
}

關鍵概念深度解析

概念說明
按值封送物件完整序列化傳輸,接收端獲得獨立副本。適用於不可變資料、小型 DTO。需 [Serializable]。
按引用封送傳遞代理,方法調用透過通道轉發至伺服器實體。適用於有狀態服務、大型物件、資源封裝。需繼承 MarshalByRefObject。
SingleCall每次客戶端呼叫創建新服務實例,呼叫結束釋放。無狀態、可擴展、預設模式。
Singleton所有客戶端共享單一實例。適合共享狀態、快取服務。
租用機制遠端物件生命周期由租用控制,預設 5 分鐘,可覆寫 InitializeLifetimeService 返回 null 禁用回收。

常見問題與避坑指南

  • 防火牆阻攔:確保 TCP 7777 通訊埠在雙向開放。
  • 序列化異常:按值傳遞的類型必須標記 [Serializable],且所有欄位皆可序列化;或實作 ISerializable 自定義邏輯。
  • 版本不匹配:客戶端與伺服器引用的 DLL 版本必須一致,否則反序列化失敗。建議共用強簽名組件。
  • 安全性:Remoting 預設無加密、無驗證。生產環境建議改用 WCF (netTcpBinding + 安全模式) 或 gRPC/ASP.NET Core。
  • 異步調用:使用 BeginInvoke/EndInvoke 或 Task.Factory.FromAsync 避免阻塞 UI 執行緒。

現代化替代方案

.NET Remoting 屬於舊版技術(.NET Framework 專屬),.NET Core / .NET 5+ 不支援。新專案推薦:

  • gRPC:高效能、跨語言、HTTP/2、內建代碼生成。
  • ASP.NET Core Web API:RESTful、成熟生態、易部署。
  • WCF (僅限 .NET Framework):企業級 WS-*、事務、可靠會話。
  • Message Queue (RabbitMQ, Azure Service Bus):解耦、削峰、最終一致性。

完整程式碼下載

本範例包含三個專案:DLL、Server、Client。編譯後先啟動 Server,再啟動 Client 即可觀察遠端調用效果。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved