[C#.NET][WCF] 實作 單向 MSMQ @self-host for NetMsmqBinding

[C#.NET][WCF] 實作 單向 MSMQ @self-host for NetMsmqBinding

MSMQ 提供一種非連接式的發送方式,也就是離線通訊方式,使得發送者可以在離線狀態下工作,網路上隨便找都一堆,本篇則是要利用 WCF Framework 下實作MSMQ

 

必要條件,開始前要安裝 Windows 環境,我準備了兩台電腦,安裝了相同的環境

安裝MSMQ  at Windows 8

SNAGHTML284dcabc

安裝完成後畫面如下:

SNAGHTML2866ae41

 

實作步驟:

Step1.建立合約類別

Step2.實作 IService1

Step3.撰寫載體程式碼

Step4.定義載體專案設定檔

Step5.定義用戶端專案設定檔

Step6.撰寫用戶端程式碼

Step7.測試


Step1.建立合約類別

@合約專案:Tako.MSMQ.Contract

[ServiceContract]
public interface IService1
{
    [OperationContract(IsOneWay = true)]
    void SendUser(User user);
}


[DataContract]
public class User
{
    [DataMember]
    public string Name { get; set; }

    [DataMember]
    public int Age { get; set; }

    public override string ToString()
    {
        return string.Format("Name:{0},Age:{1}", this.Name, this.Age);
    }
}

Note.若介面方法沒有定義 IsOneWay 或 void 當載體載入服務時就會跳出例外

image

 

Step2.實作 IService1

@載體專案:Host

public class Service1 : IService1
{
    public void SendUser(User user)
    {
        //TODO:接收到訊息要處理的事
        Console.WriteLine("接收 : " + user);
    }
}

Step3.載體程式碼

@載體專案:Host

使用 MessageQueue 建立佇列

使用 ServiceHost 裝載 WCF 服務

 

internal class Program
{
    public const String QueueName = @".\private$\takoQueue";

    private static void Main(string[] args)
    {
        if (!MessageQueue.Exists(QueueName))
        {
            MessageQueue.Create(QueueName, true);
            Console.WriteLine("佇列不存在.新增佇列");
        }
        else
        {
            Console.WriteLine("佇列已存在.");
        }

        ServiceHost serviceHost = null;
        try
        {
            serviceHost = new ServiceHost(typeof(Service1));
            serviceHost.Open();
            Console.WriteLine("服務就緒.");
            Console.WriteLine("按任意鍵離開服務.....");
            Console.WriteLine();
            Console.ReadLine();
        }
        finally
        {
            serviceHost.Close();
        }
    }
}

Note.非AD的 Queue 使用必須使用 private$,注意有 $ 符號

 

Step4.定義載體專案設定檔

@載體專案:Host

image

 

建立一個新的服務

SNAGHTML286cb912

 

選擇我們剛剛實作的 Service1

SNAGHTML286d29fc

 

選擇合約

SNAGHTML286e1854

 

SNAGHTML286e8381

 

SNAGHTML28700148

 

輸入服務名稱

net.msmq://localhost/private/TakoQueue

SNAGHTML2870b536

 

完成

image

 

Note.一個 ServiceHost 只能設定一個Endpoint

SNAGHTML28c3b2d1

 

若設定多個則會引發例外

image

 

 

 

定義Bindings

SNAGHTML2878acb3

SNAGHTML287b4c26

SNAGHTML287b69a1

 

套用

SNAGHTML287ccfc8

 

設定完成後存檔

 

完整的設定檔

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
  </startup>
  <system.serviceModel>
    <bindings>
      <netMsmqBinding>
        <binding name="netMsmqBinging.NoSecurity">
          <security mode="None" />
        </binding>
      </netMsmqBinding>
    </bindings>
    <services>
      <service name="Host.Service1">
        <endpoint address="net.msmq://localhost/private/TakoQueue" binding="netMsmqBinding"
          bindingConfiguration="netMsmqBinging.NoSecurity" contract="Tako.MSMQ.Contract.IService1" />
      </service>
    </services>
  </system.serviceModel>
</configuration>

 

Step5.定義用戶端專案設定檔

@用戶端專案:Client

image

 

建立Binding

SNAGHTML28838cf1

 

SNAGHTML28842aa8

 

SNAGHTML288475f9

 

 

 

 

建立Client

SNAGHTML28874035

 

選擇合約

SNAGHTML288dcae4

 

選擇我們剛剛定義的 netMsmqBinging.NoSecurity

SNAGHTML288e152b

 

輸入 Queue 的位置。

因為要先在本機測試所以輸入localhost,待發佈到另一台電腦再變更 ip

SNAGHTML288e442b

 

 

 

輸入名稱

SNAGHTML288e7656

 

完成

SNAGHTML288cca2d

 

完成後存檔

 

完整的設定檔如下:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
    </startup>
    <system.serviceModel>
        <client>
            <endpoint address="net.msmq://localhost/private/takoQueue" binding="netMsmqBinding"
                bindingConfiguration="netMsmqBinging.NoSecurity" contract="Tako.MSMQ.Contract.IService1"
                name="netMsmqBinding.Service1" kind="" endpointConfiguration="" />
        </client>
        <bindings>
            <netMsmqBinding>
                <binding name="netMsmqBinging.NoSecurity">
                    <security mode="None" />
                </binding>
            </netMsmqBinding>
        </bindings>
    </system.serviceModel>
</configuration>

 

Step6.撰寫用戶端程式碼

@用戶端專案:Client

 

主要是使用 ChannelFactory 將服務載入

private static void Main(string[] args)
{
    ChannelFactory<IService1> proxy = new ChannelFactory<IService1>("netMsmqBinding.Service1");
    proxy.Open();
    IService1 channel = proxy.CreateChannel();

label1:

    Console.Write("按任意鍵繼續,按ESC離開");
    var key = Console.ReadKey(true);

    if (key.Key == ConsoleKey.Escape)
    {
        Console.WriteLine("再會~!");
        proxy.Close();
        Console.ReadLine();
        return;
    }

    Console.WriteLine("");
    Console.Write("Name:");
    string name = Console.ReadLine();
    Console.Write("Age:");
    string age = Console.ReadLine();

    var user = new User() { Name = name, Age = int.Parse(age) };
    Console.WriteLine("傳送內容 : " + user);
    channel.SendUser(user);
    Console.WriteLine("傳送完成");
    goto label1;
}

 


Step7.測試

當 Client 輸入資料後,Host 便可收到訊息

image

 

Note.通訊斷線時,Client 會先把資料放在自己的 Queue 裡面,待連線後會再把資料傳給 Host 的 Queue。

 

若沒有人去 Host 拿 Queue,它就會存在這裡

SNAGHTML28989af5

 


文章出自:http://www.dotblogs.com.tw/yc421206/archive/2013/10/23/125276.aspx

範例下載:https://dotblogsfile.blob.core.windows.net/user/yc421206/1310/2013102311423330.zip

若有謬誤,煩請告知,新手發帖請多包涵


Microsoft MVP Award 2010~2017 C# 第四季
Microsoft MVP Award 2018~2022 .NET

Image result for microsoft+mvp+logo