共用方式為


傳輸:WSE 3.0 TCP 互作性

WSE 3.0 TCP 互作性傳輸範例示範如何將 TCP 雙工會話實作為自定義 Windows Communication Foundation (WCF) 傳輸。 它也會示範如何使用通道層的擴充性,透過網路與現有的已部署系統進行介面。 下列步驟示範如何建置此自定義 WCF 傳輸:

  1. 從 TCP 套接字開始,建立客戶端和伺服器的實作,使用 DIME 框架來劃定訊息界限。

  2. 建立通道處理站,以連線至 WSE TCP 服務,並透過用戶端 IDuplexSessionChannel傳送框架訊息。

  3. 建立通道接聽程式以接受連入 TCP 連線並產生對應的通道。

  4. 請確定任何網路特定的例外狀況會正規化為的適當衍生類別 CommunicationException

  5. 新增將自定義傳輸加入至通道堆疊的綁定項。 如需詳細資訊,請參閱 [加入綁定項]。

建立 IDuplexSessionChannel

撰寫 WSE 3.0 TCP 互作性傳輸的第一個步驟是在 IDuplexSessionChannel 之上建立 Socket 的實作。 WseTcpDuplexSessionChannel 衍生自 ChannelBase。 傳送訊息的邏輯包含兩個主要部分:(1)將訊息編碼成位元組,以及 (2) 將這些位元組框架並傳送到網路。

ArraySegment<byte> encodedBytes = EncodeMessage(message);

WriteData(encodedBytes);

此外,系統會取得鎖定,以確保 Send() 呼叫能保持 IDuplexSessionChannel 的順序保證,並且正確地同步處理對基礎套接字的呼叫。

WseTcpDuplexSessionChannel 使用 MessageEncoder 來將 Message 轉譯為 byte[] 並從 byte[] 迴轉譯。 因為它是傳輸, WseTcpDuplexSessionChannel 也負責套用通道設定的遠端位址。 EncodeMessage 封裝此轉換的邏輯。

this.RemoteAddress.ApplyTo(message);

return encoder.WriteMessage(message, maxBufferSize, bufferManager);

Message編碼為位元組之後,就必須經由電纜傳輸。 這需要系統來定義訊息界限。 WSE 3.0 使用 DIME 版本作為其框架通訊協定。 WriteData 封裝框架邏輯,將位元組[] 包裝成一組 DIME 記錄。

接收訊息的邏輯很類似。 主要的複雜度是處理套接字讀取傳回的位元組數比要求少的情況。 若要接收訊息,請從網路讀取位元組,解碼 DIME 框架,然後使用 WseTcpDuplexSessionChannel 將位元組陣列轉換成 MessageEncoder

基底 WseTcpDuplexSessionChannel 假設它已收到連接的套接字。 基類會處理套接字關機。 有三個位置與套接字關閉相關聯:

  • OnAbort - 粗暴地關閉套接字『硬關閉』。

  • On[Begin]Close -- 優雅地關閉套接字(軟關閉)。

  • 關閉輸出會話 -- 關閉輸出資料流(半關閉)。

通道處理站

撰寫 TCP 傳輸的下一個步驟是建立 用戶端通道的 IChannelFactory 實作。

  • WseTcpChannelFactory 衍生自 ChannelFactoryBase<IDuplexSessionChannel>。 這是覆寫 OnCreateChannel 以產生用戶端通道的處理站。

protected override IDuplexSessionChannel OnCreateChannel(EndpointAddress remoteAddress, Uri via)

{

return new ClientWseTcpDuplexSessionChannel(encoderFactory, bufferManager, remoteAddress, via, this);

}

  • ClientWseTcpDuplexSessionChannel 將邏輯新增到基礎 WseTcpDuplexSessionChannel ,以在 channel.Open 時連線到 TCP 伺服器。 首先,主機名會解析為IP位址,如下列程式代碼所示。

hostEntry = Dns.GetHostEntry(Via.Host);

  • 然後主機名會連線到迴圈中第一個可用的IP位址,如下列程式代碼所示。

IPAddress address = hostEntry.AddressList[i];

socket = new Socket(address.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

socket.Connect(new IPEndPoint(address, port));

  • 做為通道合約的一部分,會包裝任何網域特定的例外狀況,例如 SocketException 在中 CommunicationException

通道監聽器

撰寫 TCP 傳輸的下一個步驟是建立 IChannelListener 的實作,用於接收伺服器通道。

  • WseTcpChannelListener 衍生自 ChannelListenerBase<IDuplexSessionChannel> ,並覆寫 On[Begin]Open 和 On[Begin]Close 來控制其接聽套接字的生命周期。 在 OnOpen 中,會建立套接字以接聽IP_ANY。 更進階的實作還可以建立第二個套接字,用來監聽IPv6。 它們也可以允許在主機名中指定IP位址。

IPEndPoint localEndpoint = new IPEndPoint(IPAddress.Any, uri.Port);

this.listenSocket = new Socket(localEndpoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

this.listenSocket.Bind(localEndpoint);

this.listenSocket.Listen(10);

接受新的套接字時,伺服器通道會使用此套接字初始化。 所有的輸入和輸出都已經在基礎類別中實作,因此此頻道負責初始化套接字。

新增綁定項

現在工廠和通道已經建置完成,因此必須透過系結向 Service Model 執行時間公開它們。 系結是綁定項的集合,表示與服務地址相關聯的通訊堆棧。 堆疊中的每個項目都會以綁定項表示。

在範例中,綁定項是 WseTcpTransportBindingElement,其衍生自 TransportBindingElement。 它支援 IDuplexSessionChannel 並覆寫下列方法來建置與系結相關聯的處理站。

public IChannelFactory<TChannel> BuildChannelFactory<TChannel>(BindingContext context)

{

return (IChannelFactory<TChannel>)(object)new WseTcpChannelFactory(this, context);

}

public IChannelListener<TChannel> BuildChannelListener<TChannel>(BindingContext context)

{

return (IChannelListener<TChannel>)(object)new WseTcpChannelListener(this, context);

}

它還包含用於複製BindingElement並傳回我們方案的成員(wse.tcp)。

WSE TCP 測試主控台

TestCode.cs提供使用此範例傳輸的測試程序代碼。 下列指示示範如何設定 WSE TcpSyncStockService 範例。

測試程式碼會建立自定義系結,使用 MTOM 作為編碼方式,並使用WseTcpTransport作為傳輸方式。 它也會設定 AddressingVersion 以符合 WSE 3.0,如下列程式代碼所示。

CustomBinding binding = new CustomBinding();

MtomMessageEncodingBindingElement mtomBindingElement = new MtomMessageEncodingBindingElement();

mtomBindingElement.MessageVersion = MessageVersion.Soap11WSAddressingAugust2004;

binding.Elements.Add(mtomBindingElement);

binding.Elements.Add(new WseTcpTransportBindingElement());

它由兩個測試組成:一個測試會使用 WSE 3.0 WSDL 生成的程式碼來設定類型化的客戶端。 第二個測試使用 WCF 作為客戶端和服務器,直接透過通道 API 傳送消息。

執行範例時,預期會有下列輸出。

用戶端:

Calling soap://stockservice.contoso.com/wse/samples/2003/06/TcpSyncStockService

Symbol: FABRIKAM
        Name: Fabrikam, Inc.
        Last Price: 120

Symbol: CONTOSO
        Name: Contoso Corp.
        Last Price: 50.07
Press enter.

Received Action: http://SayHello
Received Body: to you.
Hello to you.
Press enter.

Received Action: http://NotHello
Received Body: to me.
Press enter.

伺服器:

Listening for messages at soap://stockservice.contoso.com/wse/samples/2003/06/TcpSyncStockService

Press any key to exit when done...

Request received.
Symbols:
        FABRIKAM
        CONTOSO

設定、建置和執行範例

  1. 若要執行此範例,您必須已安裝 Microsoft .NET 和 WSE 範例的 Web 服務增強功能 (WSE) 3.0TcpSyncStockService

備註

因為 Windows Server 2008 不支援 WSE 3.0,所以您無法在該作系統上安裝或執行 TcpSyncStockService 範例。

  1. TcpSyncStockService安裝範例之後,請執行下列動作:

    1. 在 Visual Studio 中開啟 TcpSyncStockService。 ( TcpSyncStockService 範例 會隨 WSE 3.0 一起安裝。這不是此範例程式代碼的一部分。

    2. 將 StockService 專案設定為啟始專案。

    3. 在 StockService 項目中開啟StockService.cs,並將 類別上的 StockService [Policy] 屬性批注化。 這會停用範例的安全性。 雖然 WCF 可以與 WSE 3.0 安全端點互通,但安全性會停用,讓此範例著重於自定義 TCP 傳輸。

    4. F5 以啟動 TcpSyncStockService。 服務會在新的控制台視窗中啟動。

    5. 在 Visual Studio 中開啟此 TCP 傳輸範例。

    6. 更新 TestCode.cs 中的 「hostname」 變數,以符合執行 TcpSyncStockService的電腦名稱。

    7. F5 以啟動 TCP 傳輸範例。

    8. TCP 傳輸測試用戶端會在新的控制台中啟動。 用戶端會向服務要求股票報價,然後在其控制台視窗中顯示結果。