消息隊(duì)列不同于傳統(tǒng)的請(qǐng)求響應(yīng)模式,它是客戶端把消息發(fā)送給請(qǐng)求消息隊(duì)列,服務(wù)可以稍后對(duì)消息進(jìn)行處理并把處理結(jié)果發(fā)送給響應(yīng)隊(duì)列,而后客戶端從響應(yīng)隊(duì)列讀取服務(wù)處理后的消息。而且使用消息隊(duì)列可以使客戶端實(shí)現(xiàn)脫機(jī)工作。脫機(jī)應(yīng)用程序必須有本地緩存數(shù)據(jù),要采用異步通訊而且要把消息持久化,在與服務(wù)器聯(lián)機(jī)后將消息發(fā)送出去。WCF是使用NetMsmqBinding來(lái)支持消息隊(duì)列的,傳輸消息不是通過(guò)TCP或HTTP等,而是通過(guò)微軟消息隊(duì)列(MSMQ),這是Windows組件,可以通過(guò)1)控制面板2)程序和功能:打開(kāi)或關(guān)閉Windows功能3)出現(xiàn)如下界面,點(diǎn)確定即可安裝。
安裝成功后可以右擊我的電腦選擇管理而后會(huì)有如下界面:
理論也不說(shuō)那么多了,MSDN上說(shuō)的很詳細(xì),還是寫(xiě)些相對(duì)簡(jiǎn)單清晰的代碼的整體上把握下消息隊(duì)列,有時(shí)候看書(shū)不是太明白的地方,調(diào)試下代碼或許會(huì)有種豁然開(kāi)朗的感覺(jué)。因?yàn)橐S護(hù)服務(wù)端和客戶端雙向通訊,所以需要兩個(gè)隊(duì)列,兩個(gè)單向操作契約。而客戶端的功能既要發(fā)送消息到請(qǐng)求消息隊(duì)列又要從響應(yīng)消息隊(duì)列讀取響應(yīng)消息,服務(wù)端則需要從調(diào)用隊(duì)列讀取消息進(jìn)行處理,處理后發(fā)送的響應(yīng)消息隊(duì)列。實(shí)際上客戶端和服務(wù)端并沒(méi)有直接通訊,而是通過(guò)兩個(gè)隊(duì)列來(lái)進(jìn)行通訊的。
請(qǐng)求契約:
using
System;
using
System.ServiceModel;
namespace
IFruit
{
[ServiceContract]
public
interface
IFruitService
{
[OperationContract(IsOneWay
=
true
)]
void
GetFruitInfo(
string
fruitName,
string
price);
}
}
請(qǐng)求服務(wù)實(shí)現(xiàn):
using
System;
using
System.Messaging;
using
System.ServiceModel;
using
IFruit;
using
IFruitResponse;
namespace
FruitSvc
{
[ServiceBehavior(InstanceContextMode
=
InstanceContextMode.PerCall)]
public
class
FruitService:IFruitService
{
[OperationBehavior(TransactionScopeRequired
=
true
)]
public
void
GetFruitInfo(
string
fruitName,
string
price)
{
string
info
=
string
.Empty;
ExceptionDetail error
=
null
;
try
{
info
=
string
.Format(
"
The Fruit Name Is {0} And Price Is {1}
"
, fruitName, price);
}
catch
(Exception ex)
{
error
=
new
ExceptionDetail(ex);
}
finally
{
//
創(chuàng)建隊(duì)列
string
queueName
=
"
.\\private$\\FruitResponseQueue
"
;
if
(
!
MessageQueue.Exists(queueName))
{
MessageQueue.Create(queueName,
true
);
}
//
把處理后的消息放到響應(yīng)消息隊(duì)列
EndpointAddress address
=
new
EndpointAddress(
"
net.msmq://localhost/private/FruitResponseQueue
"
);
NetMsmqBinding binding
=
new
NetMsmqBinding();
binding.Security.Mode
=
NetMsmqSecurityMode.None;
using
(ChannelFactory
<
IFruitResponseService
>
factory
=
new
ChannelFactory
<
IFruitResponseService
>
(binding,
address))
{
IFruitResponseService response
=
factory.CreateChannel();
response.OnGetFruitInfoCompleted(info, error);
}
}
}
}
}
響應(yīng)契約:
using
System;
using
System.ServiceModel;
namespace
IFruitResponse
{
[ServiceContract]
public
interface
IFruitResponseService
{
[OperationContract(IsOneWay
=
true
)]
void
OnGetFruitInfoCompleted(
string
fruitInfo, ExceptionDetail error);
}
}
響應(yīng)服務(wù)實(shí)現(xiàn):
using
System;
using
System.Collections.Generic;
using
System.ServiceModel;
using
IFruitResponse;
namespace
FruitResponse
{
//
定義一泛型委托
public
delegate
void
GenericEventHandler
<
T
>
(T t);
[ServiceBehavior(InstanceContextMode
=
InstanceContextMode.PerCall)]
public
class
FruitResponseService : IFruitResponseService
{
//
聲明并初始化一委托事件
public
static
event
GenericEventHandler
<
string
>
GetFruitInfoCompleted
=
delegate
{ };
[OperationBehavior(TransactionScopeRequired
=
true
)]
public
void
OnGetFruitInfoCompleted(
string
fruitInfo, ExceptionDetail error)
{
if
(error
==
null
)
{
GetFruitInfoCompleted(fruitInfo);
}
}
}
}
客戶端服務(wù)寄存:
using
System;
using
System.ServiceModel;
using
System.Messaging;
using
FruitResponse;
using
IFruit;
namespace
FruitClientHost
{
class
Program
{
static
void
Main(
string
[] args)
{
//
GetFruitInfoCompleted發(fā)生后調(diào)用OnGetFruitInfoCompleted方法
FruitResponseService.GetFruitInfoCompleted
+=
Program.OnGetFruitInfoCompleted;
//
創(chuàng)建兩個(gè)隊(duì)列
string
queueName
=
"
.\\private$\\GetFruitInfoQueue
"
;
if
(
!
MessageQueue.Exists(queueName))
{
MessageQueue.Create(queueName,
true
);
}
string
queueName1
=
"
.\\private$\\FruitResponseQueue
"
;
if
(
!
MessageQueue.Exists(queueName1))
{
MessageQueue.Create(queueName1,
true
);
}
//
接收響應(yīng)消息
ServiceHost fruitHost
=
new
ServiceHost(
typeof
(FruitResponseService),
new
Uri(
"
net.msmq://localhost/private/FruitResponseQueue
"
));
NetMsmqBinding netMsmqBind
=
new
NetMsmqBinding();
netMsmqBind.Security.Mode
=
NetMsmqSecurityMode.None;
fruitHost.AddServiceEndpoint(
typeof
(IFruitResponse.IFruitResponseService), netMsmqBind,
""
);
fruitHost.Open();
//
發(fā)送請(qǐng)求消息到請(qǐng)求隊(duì)列
EndpointAddress address
=
new
EndpointAddress(
"
net.msmq://localhost/private/GetFruitInfoQueue
"
);
NetMsmqBinding binding
=
new
NetMsmqBinding();
binding.Security.Mode
=
NetMsmqSecurityMode.None;
using
(ChannelFactory
<
IFruitService
>
factory
=
new
ChannelFactory
<
IFruitService
>
(binding, address))
{
IFruitService fruit
=
factory.CreateChannel();
fruit.GetFruitInfo(
"
banana
"
,
"
6.00
"
);
}
Console.WriteLine(
"
The Client Is Running ...
"
);
Console.ReadLine();
fruitHost.Close();
}
static
void
OnGetFruitInfoCompleted(
string
fruitInfo)
{
Console.WriteLine(fruitInfo);
}
}
}
服務(wù)端服務(wù)寄存:
using
System;
using
System.ServiceModel;
using
FruitSvc;
using
IFruit;
namespace
FruitResponseHost
{
class
Program
{
static
void
Main(
string
[] args)
{
ServiceHost fruitServiceHost
=
new
ServiceHost(
typeof
(FruitService),
new
Uri(
"
net.msmq://localhost/private/GetFruitInfoQueue
"
));
NetMsmqBinding netMsmqBind
=
new
NetMsmqBinding();
netMsmqBind.Security.Mode
=
NetMsmqSecurityMode.None;
fruitServiceHost.AddServiceEndpoint(
typeof
(IFruitService), netMsmqBind,
""
);
fruitServiceHost.Open();
Console.WriteLine(
"
The Service Is Running ...
"
);
Console.ReadLine();
fruitServiceHost.Close();
}
}
}
運(yùn)行程序,先啟動(dòng)客戶端,此時(shí)的消息可以通過(guò)MSMQ管理控制臺(tái)進(jìn)行管理:
從管理控制臺(tái)可以看出GetFruitInfoQueue有一條消息,而后啟動(dòng)服務(wù)端:
客戶端已經(jīng)呈現(xiàn)出服務(wù)處理后的消息信息,GetFruitInfoQueue的消息已經(jīng)被服務(wù)處理了,消息數(shù)目變?yōu)?。
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061
微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元

