.NET Remoting 體系結構 之 信道的功能和配置 (一)


信道

  信道用於.NET 客戶端和服務器之間的通信。.NET Framework 4 發布的信道類使用 TCP 、HTTP 或IPC 進行通信。我們可以為其他的協議創建自定義信道。 HTTP 信道使用 HTTP 協議進行通信。因為防火牆通常讓端口 80 處於打開的狀態,所以客戶端能 夠訪問 Web 服務器,因為.NET Remoting Web 服務可以偵聽端口 80,所以客戶端更容易使用它們。 雖然在 Internet 上也可以使用 TCP 信道,但是必須配置防火牆,這樣客戶端能夠訪問 TCP 信道 所使用的指定端口。與 HTTP 信道相比,在內部網環境中使用 TCP 信道能夠進行更加高效的通信。 IPC 信道適合於在單個系統上進行跨進程的通信。因為它使用 Windows 進程間通信機制,所 以它比其他信道快。當執行遠程對象上的方法調用時,導致客戶信道對象就把消息發送到遠程信道對象中。 服務器應用程序和客戶端應用程序都必須創建信道。 下面的代碼說明了如何在服務器端創建 TcpServerChannel:

using System.Runtime.Remoting.Channels.Tcp; 
//省略...
TcpServerChannel channel = new TcpServerChannel(8086); 

 構造函數的參數指定 TCP 套接字偵聽哪個端口。服務器信道必須指定一個眾所周知的端口,在 訪問服務器時,客戶端必須使用該端口。但是,在客戶端上創建 TcpClientChannel 時,不必指定一 個眾所周知的端口,TcpClientChannel 的默認構造函數會選擇一個可用端口,在客戶端與服務器連接 時,該端口被傳遞給服務器,以便服務器能夠把數據返回給客戶端。 創建新的信道實例,會使套接字立即轉換到偵聽狀態,在命令行中輸入 netstat –a,可以驗證套 接字是否處於偵聽狀態。

HTTP 信道的使用方式類似於 TCP 信道。可以指定服務器能在哪個端口上創建偵聽套接字。 服務器可以偵聽多個信道。下面的代碼創建並注冊 HTTP、TCP 和IPC 信道:

var tcpChannel = new TcpServerChannel(8086); 
var httpChannel = new HttpServerChannel(8085);
 var ipcChannel = new IpcServerChannel("myIPCPort"); 
// register the channels 
ChannelServices.RegisterChannel(tcpChannel, true); 
ChannelServices.RegisterChannel(httpChannel, false); 
ChannelServices.RegisterChannel(ipcChannel, true); 

 信道類必須實現 IChannel 接口。IChannel 接口有以下兩個屬性:

●  ChannelName 屬性是只讀的,它返回信道的名稱。信道的名稱取決於協議的類型,例如, HTTP 信道的名稱為 HTTP。

●  ChannelPriority 屬性也是只讀的。在客戶端和服務器之間可以使用多個信道進行通信,優先 級定義信道的次序。在客戶端上,具有較高優先級的信道首先連接到服務器上。優先級值 越高,優先級就越高,其默認值是 1,但允許使用負值創建較低的優先級。

實現的其他接口要根據信道的類型決定,服務器信道實現 IChannelReceiver 接口,而客戶端信 道實現 IChannelSender 接口。 HTTPChannel、TcpChannel 和 IPCChannel 類都可以用於服務器和客戶端。它們實現 IChannelSender 和 IChannelReceiver 接口。這些接口都派生自 IChannel 接口。 客戶端的 IchannelSender 接口除了有 Ichannel 接口之外,還有一個 CreateMessageSink()方法,這 個方法返回一個實現 IMessageSink 接口的對象。IMessageSink 接口可以把同步和異步消息放到信道 中。在使用服務器端的接口 IChannelReceiver 時,通過 StartListening()方法可以把信道設置為偵聽狀 態,而通過 StopListening()方法則可以停止對信道的偵聽。ChannelData 屬性用於訪問所獲取的數據。

使用信道類的屬性,可以獲取信道的配置信息。HTTP和TCP 信道都有 ChannelName、ChannelPriority 和ChannelData 屬性。使用 ChannelData 屬性可以獲取存儲在 ChannelDataStore 類中的 URI 信息。此外, HttpServerChannel 類還有一個 Scheme 屬性。下面的代碼顯示一個輔助方法 ShowChannelProperties(),該 方法在文件中顯示對應的信息:

 1         static void ShowChannelProperties(IChannelReceiver channel)
 2         {
 3             Console.WriteLine("Name:  {0}", channel.ChannelName);
 4             Console.WriteLine("Priority: {0}", channel.ChannelPriority);
 5             if (channel is TcpChannel)
 6             {
 7                 TcpChannel tcpChannel = channel as TcpChannel;
 8                 Console.WriteLine("is secured: {0}", tcpChannel.IsSecured);
 9             }
10 
11             if (channel is HttpServerChannel)
12             {
13                 HttpServerChannel httpChannel = channel as HttpServerChannel;
14                 Console.WriteLine("Scheme: {0}", httpChannel.ChannelScheme);
15             }
16 
17             ChannelDataStore data = (ChannelDataStore)channel.ChannelData;
18             if (data != null)
19             {
20                 foreach (string uri in data.ChannelUris)
21                 {
22                     Console.WriteLine("URI: " + uri);
23                 }
24             }
25             Console.WriteLine();
26         }

  設置信道屬性
使用構造函數 TCPServerChannel(IDictionary,IServerChannelSinkProvider),可以在一個列表中設 置信道的所有屬性。Dictionary 泛型類實現 IDictionary 接口,因此,使用這個類可以設置 Name、 Priority 和 Port 屬性。為了使用 Dictionary 類,必須導入 System.Collections.Generic 名稱空間。 在 TcpServerChannel 類的構造函數中,除了參數 IDictionary 之外,還可以傳遞實現 IServerChannelSinkProvider 接口的對象。在本例中,設置 BinaryServerFormatterSinkProvider 而不設置 SoapServerFormatterSinkProvider,前者是 HttpServerChannel 的默認值。BinaryServerFormatterSinkProvider 類的默認實現代碼把 BinaryServerFormatterSink 類與使用 BinaryFormatter 對象的信道聯系起來,以轉換 數據,便於傳輸:

1             var properties = new Dictionary<string, string>();
2             properties["name"] = "HTTP Channel with a Binary Formatter";
3             properties["priority"] = "15";
4             properties["port"] = "8085";
5             var sinkProvider = new BinaryServerFormatterSinkProvider();
6             var httpChannel = new HttpServerChannel(properties, sinkProvider);

根據信道的類型,可以指定不同的屬性。TCP 和HTTP 信道都支持本例中使用的 name 和priority 信道屬性。這些信道也支持其他屬性,如 bindTo,如果計算機配置了多個 IP 地址,bindTo 指定綁定可以使用的 IP 地址。TCP 服務器信道支持 rejectRemoteRequests,只允許從本地計算機上連接客 戶端。

信道的“可插入性”

創建的自定義信道可以使用 HTTP、TCP 和 IPC 之外的其他傳輸協議發送消息。此外,也可以 對現有的信道進行擴展,從而提供更多功能:

●  發送部分必須實現 IChannelSender 接口。重要的部分是 CreateMessageSink()方法,在該方 法中,客戶端要發送 URL,此外,使用這個方法可以實例化與服務器的連接。在這里必須 創建消息接收器,代理使用該消息接收器把消息發送到信道中。

●  接收部分必須實現 IChannelReceiver 接口。必須在 ChannelData 的get 屬性中啟動偵聽功能。 然后,可以等待另一個線程接收來自客戶端的數據。在打亂消息之后,使用 ChannelServices. SyncDispatchMessage()方法把消息分配給對象。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM