本体系服务端双工通讯包涵三种完结方式:一、使用Socket营造;2、使用WCF营造。本文为使用WCF营造服务端的双工通讯,客户端同样应用Html5的WebSocket技术拓展调用。

本类别服务端双工通讯包罗两种完结格局:一、使用Socket营造;二、使用WCF营造。本文为运用WCF创设服务端的双工通讯,客户端同样采取Html伍的WebSocket技术进行调用。

前言:         

 

*WCF初探-5:WCF消息沟通情势之双工通信(Duplex)***博文中,小编执教了双工通讯服务的1个行使场景,即订阅和布告情势,这一篇,小编将经过2个音讯发送的例证讲解一下WCF客户端怎么样为双工服务成立回调对象。

双工服务钦赐三个回调协定,客户端应用程序必须达成该协定以便提供1个该服务能够依照协定要求调用的回调对象。就算回调对象不是全体的劳务(例如,您不能使用回调对象运营贰个大路),不过为了落到实处和布局,这么些回调对象能够被视为1种服务。

双工服务的客户端必须:

  • 金镶玉裹福禄双全3个回调协定类。
  • 创设回调协定实现类的三个实例,并接纳该实例成立传递给 WCF
    客户端构造函数的 System.ServiceModel.InstanceContext 对象。
  • 调用操作并拍卖操作回调。

       双工 WCF
客户端对象除了会公开支持回调所必要的功用(包涵回调服务的布局)以外,其余的职能和它们的非双工对应项相同。

 

一、创建WCF服务库Wcf.Duplex.Library:

一、创建WCF服务库Wcf.Duplex.Library:

以身作则表明:

 

  • Service服务契约中定义了1个发送方法Send,选择IsOneWay=true,供客户端调用,向服务端发送消息。Service中还提供了用来双工通讯的回调接口IMessageExchangeCallback,该接口中定义了服务端接收新闻后向客户端发送消息的主意Receive,此方式就是客户端发送信息到服务端后,服务端调用回调方法,将音信发送到客户端。
  • Client须求达成双工协定回调接口的类CallBackHandler,并贯彻Receive方法。
  • 本着双工协定生成的 WCF 客户端必要在组织时提供1个 InstanceContext
    类。此 InstanceContext
    类用作实现回调接口并处理从服务发送回的消息的指标所在的职位。InstanceContext
    类是用 CallbackHandler
    类的实例构造的。此目的处理通过回调接口从服务发送到客户端的新闻。

  亚洲城ca88 1

 

一.定义协议的服务接口:

一.概念协议的劳动接口:

 WCF客户端为双工服务创设回调对象示例

 

  • 缓解方案如下:

  亚洲城ca88 2

  • 工程组织表明:
  1. Service:类库程序,定义服务契约接口和回调接口,落成劳务契约。在IMessageExchange中定义了Send方法,并且还定义了双工服务回调接口 IMessageExchangeCallback。

    IMessageExchange.cs的代码如下:

using System.ServiceModel;
using System.Collections.Generic;
using System.Runtime.Serialization;

namespace Service
{
    [ServiceContract(SessionMode = SessionMode.Required, CallbackContract = typeof(IMessageExchangeCallback))]
    public interface IMessageExchange
    {
        [OperationContract(IsOneWay=true)]
        void Send(string message);
    }

    public interface IMessageExchangeCallback
    {
        [OperationContract(IsOneWay = true)]
        void Receive(string message);
    }
}                                                

    MessageExchange.cs的代码如下: 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;

namespace Service
{ 
    [ServiceBehavior(InstanceContextMode=InstanceContextMode.PerSession)]
    public class MessageExchange : IMessageExchange
    {
        public void Send(string message)
        {
            Console.WriteLine("服务端监听客户端发出的消息:" + message);
            Callback.Receive(message);

        }

        IMessageExchangeCallback Callback
        {
            get
            {
                return OperationContext.Current.GetCallbackChannel<IMessageExchangeCallback>();
            }
        }
    }
}

专注:回调契约接口IMessageExchangeCallback中的Receive方法是在客户端完成的,所以只要急需在服务端调用回调方法就不可能不通过当前操作的实例上下文来收获,即上边代码中的Callback对象。

  二.
 Host:控制台应用程序。提供劳务寄宿程序,添加对Srevice程序集的引用。落成布局文件和代码就能够承接服务。

       Program.cs的代码如下:

  亚洲城ca88 3亚洲城ca88 4

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Service;
using System.ServiceModel;

namespace Host
{
    class Program
    {
        static void Main(string[] args)
        {
            using (ServiceHost host = new ServiceHost(typeof(MessageExchange)))
            {
                host.Opened += delegate { Console.WriteLine("服务已经启动,按任意键终止!"); };
                host.Open();
                Console.Read();
            }
        }
    }
}

View Code

    App.config的代码如下:

  亚洲城ca88 5亚洲城ca88 6

<?xml version="1.0"?>
<configuration>
    <system.serviceModel>

        <services>
            <service name="Service.MessageExchange" behaviorConfiguration="mexBehavior">
                <host>
                    <baseAddresses>
                        <add baseAddress="http://localhost:1234/MessageExchange/"/>
                    </baseAddresses>
                </host>
                <endpoint address="" binding="wsDualHttpBinding" contract="Service.IMessageExchange" />
                <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
            </service>
        </services>

        <behaviors>
            <serviceBehaviors>
                <behavior name="mexBehavior">
                    <serviceMetadata httpGetEnabled="true"/>
                    <serviceDebug includeExceptionDetailInFaults="true"/>
                </behavior>
            </serviceBehaviors>
        </behaviors>

    </system.serviceModel>
</configuration>

View Code

  3.
 Client:控制台应用程序。客户端程序,运行服务承载程序Host后,添加对劳务地点的引用,将命名空间修改为

    MessageExchangeServiceRef,之后在Program.cs完结对双工服务回调接口IMessageExchangeCallback的完成和对劳动章程的调用。Program.cs的代码如下:

using System;
using Client.MessageExchangeServiceRef;
using System.ServiceModel;

namespace Client1
{

    public class CallBackHandler : IMessageExchangeCallback
    {
        public void Receive(string message)
        {
            Console.WriteLine("客户端监听服务端接收的消息:" + message);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            InstanceContext instanceContext = new InstanceContext(new CallBackHandler());
            MessageExchangeClient proxy = new MessageExchangeClient(instanceContext);
            proxy.Send("Wcf Duplex");

            Console.Read();
        }
    }
}

  运转结果如下:

  亚洲城ca88 7

亚洲城ca88 8亚洲城ca88 9

亚洲城ca88 10亚洲城ca88 11

总结:

 

  • 正文模拟了客户端向服务端发送消息,服务端接收到新闻后,将监听到的音讯呈现在客户端。希望通过本示例对双工通讯有开拓进取1的认识,关于实例和对话,笔者将在前边的博文中做分析。

亚洲城ca88 12

 1 [ServiceContract]
 2 public interface IWebSocketEchoCallback
 3 {
 4 [OperationContract(IsOneWay = true, Action = "*")]
 5 void Send(Message message);
 6 }
 7 
 8 [ServiceContract(CallbackContract = typeof(IWebSocketEchoCallback))]
 9 public interface IWebSocketEcho
10 {
11 [OperationContract(IsOneWay = true, Action = "*")]
12 void Receive(Message message);
13 }
 1 [ServiceContract]
 2 public interface IWebSocketEchoCallback
 3 {
 4 [OperationContract(IsOneWay = true, Action = "*")]
 5 void Send(Message message);
 6 }
 7 
 8 [ServiceContract(CallbackContract = typeof(IWebSocketEchoCallback))]
 9 public interface IWebSocketEcho
10 {
11 [OperationContract(IsOneWay = true, Action = "*")]
12 void Receive(Message message);
13 }

View Code

View Code

注意:

注意:

OperationContract中的Action,一定要设置。

OperationContract中的Action,一定要设置。

IWebSocketEcho接口中:只可以定义3个OperationContract(IsOneWay = true,
Action = “*”)方法入口,不然使用WebSocket连接时会报错

IWebSocketEcho接口中:只好定义三个OperationContract(IsOneWay = true,
Action = “*”)方法入口,否则使用WebSocket连接时会报错

IWebSocketEchoCallback
回调接口中:可以定义几个OperationContract(IsOneWay = true, Action =
“*”)方法

IWebSocketEchoCallback
回调接口中:能够定义四个OperationContract(IsOneWay = true, Action =
“*”)方法

2.兑现劳务协议,并定义叁个石英钟,定时调用回调方法,发送消息给客户端:

贰.兑现劳务协议,并定义1个机械钟,定时调用回调方法,发送音信给客户端:

亚洲城ca88 13亚洲城ca88 14

亚洲城ca88 15亚洲城ca88 16

 1 public class EchoService : IWebSocketEcho
 2 {
 3 
 4 IWebSocketEchoCallback _callback = null;
 5 
 6 public EchoService()
 7 {
 8 
 9 //获取回调信道
10 _callback =
11 OperationContext.Current.GetCallbackChannel<IWebSocketEchoCallback>();
12 
13 Timer time = new Timer(10000);
14 time.Elapsed += time_Elapsed;
15 time.Start();
16 }
17 void time_Elapsed(object sender, ElapsedEventArgs e)
18 {
19 _callback.Send(CreateMessage("Message From WebSockets Host" + " " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")));
20 }
21 public void Receive(Message message)
22 {
23 if (message == null)
24 {
25 throw new ArgumentNullException("message");
26 }
27 
28 WebSocketMessageProperty property =
29 (WebSocketMessageProperty)message.Properties["WebSocketMessageProperty"];
30 WebSocketContext context = property.WebSocketContext;
31 var queryParameters = HttpUtility.ParseQueryString(context.RequestUri.Query);
32 string content = string.Empty;
33 
34 if (!message.IsEmpty)
35 {
36 byte[] body = message.GetBody<byte[]>();
37 content = Encoding.UTF8.GetString(body);
38 }
39 
40 // Do something with the content/queryParams
41 // ...
42 
43 string str = null;
44 if (string.IsNullOrEmpty(content)) // Connection open message
45 {
46 str = "Opening connection from user " +
47 queryParameters["Name"].ToString();
48 }
49 else // Message received from client
50 {
51 str = "Received message: " + content;
52 }
53 wcf.websocket.forweb.LogHelper.log.Error(str);
54 _callback.Send(CreateMessage(str));
55 }
56 
57 private Message CreateMessage(string content)
58 {
59 Message message = ByteStreamMessage.CreateMessage(
60 new ArraySegment<byte>(
61 Encoding.UTF8.GetBytes(content)));
62 message.Properties["WebSocketMessageProperty"] =
63 new WebSocketMessageProperty { MessageType = WebSocketMessageType.Text };
64 
65 return message;
66 }
67 }
 1 public class EchoService : IWebSocketEcho
 2 {
 3 
 4 IWebSocketEchoCallback _callback = null;
 5 
 6 public EchoService()
 7 {
 8 
 9 //获取回调信道
10 _callback =
11 OperationContext.Current.GetCallbackChannel<IWebSocketEchoCallback>();
12 
13 Timer time = new Timer(10000);
14 time.Elapsed += time_Elapsed;
15 time.Start();
16 }
17 void time_Elapsed(object sender, ElapsedEventArgs e)
18 {
19 _callback.Send(CreateMessage("Message From WebSockets Host" + " " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")));
20 }
21 public void Receive(Message message)
22 {
23 if (message == null)
24 {
25 throw new ArgumentNullException("message");
26 }
27 
28 WebSocketMessageProperty property =
29 (WebSocketMessageProperty)message.Properties["WebSocketMessageProperty"];
30 WebSocketContext context = property.WebSocketContext;
31 var queryParameters = HttpUtility.ParseQueryString(context.RequestUri.Query);
32 string content = string.Empty;
33 
34 if (!message.IsEmpty)
35 {
36 byte[] body = message.GetBody<byte[]>();
37 content = Encoding.UTF8.GetString(body);
38 }
39 
40 // Do something with the content/queryParams
41 // ...
42 
43 string str = null;
44 if (string.IsNullOrEmpty(content)) // Connection open message
45 {
46 str = "Opening connection from user " +
47 queryParameters["Name"].ToString();
48 }
49 else // Message received from client
50 {
51 str = "Received message: " + content;
52 }
53 wcf.websocket.forweb.LogHelper.log.Error(str);
54 _callback.Send(CreateMessage(str));
55 }
56 
57 private Message CreateMessage(string content)
58 {
59 Message message = ByteStreamMessage.CreateMessage(
60 new ArraySegment<byte>(
61 Encoding.UTF8.GetBytes(content)));
62 message.Properties["WebSocketMessageProperty"] =
63 new WebSocketMessageProperty { MessageType = WebSocketMessageType.Text };
64 
65 return message;
66 }
67 }

View Code

View Code

2.新建WEB项目,在品种中引用第1步建立的WCF服务库Wcf.Duplex.Library。

二.新建WEB项目,在项目中援引第二步建立的WCF服务库Wcf.Duplex.Library。

1.打开Global.asax.cs的文件,在Application_Start扩展以下代码:

1.打开Global.asax.cs的文件,在Application_Start增添以下代码:

RouteTable.Routes.Add(new ServiceRoute("EchoService",new ServiceHostFactory(),typeof(EchoService)));
RouteTable.Routes.Add(new ServiceRoute("EchoService",new ServiceHostFactory(),typeof(EchoService)));

 

 

证实:扩大服务路由的时候,路由前缀能够任由设置;瑟维斯Type,须求安装为WCF服务库的EchoService类。

注解:扩张服务路由的时候,路由前缀能够随便设置;ServiceType,要求设置为WCF服务库的Echo瑟维斯类。

2.配置WEB.Config:

2.配置WEB.Config:

亚洲城ca88 17亚洲城ca88 18

亚洲城ca88 19亚洲城ca88 20

<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />

<services>

<service name="Wcf.Duplex.Library.EchoService"><!--此处为服务类,需要修改为本项目的服务类-->
<endpoint address=""

binding="customBinding"

bindingConfiguration="webSocket"

contract="Wcf.Duplex.Library.IWebSocketEcho" /><!--此处为服务的协议接口,需要修改为本项目对应的服务接口-->
</service>
</services>
<bindings>
<customBinding>
<binding name="webSocket">
<byteStreamMessageEncoding/>
<httpTransport>
<webSocketSettings transportUsage="Always"

createNotificationOnConnection="true"/>
</httpTransport>
</binding>
</customBinding>
</bindings>
</system.serviceModel>
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />

<services>

<service name="Wcf.Duplex.Library.EchoService"><!--此处为服务类,需要修改为本项目的服务类-->
<endpoint address=""

binding="customBinding"

bindingConfiguration="webSocket"

contract="Wcf.Duplex.Library.IWebSocketEcho" /><!--此处为服务的协议接口,需要修改为本项目对应的服务接口-->
</service>
</services>
<bindings>
<customBinding>
<binding name="webSocket">
<byteStreamMessageEncoding/>
<httpTransport>
<webSocketSettings transportUsage="Always"

createNotificationOnConnection="true"/>
</httpTransport>
</binding>
</customBinding>
</bindings>
</system.serviceModel>

View Code

View Code

 

 

三.在时下项目中加进页面testWebSocket.html,使用WebSocket调用服务

三.在近日项目中加进页面testWebSocket.html,使用WebSocket调用服务

亚洲城ca88 21亚洲城ca88 22

亚洲城ca88 23亚洲城ca88 24

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>WebSockets客户端示例</title>
</head>
<script>
var webSocket;
function connect() {
try {
var readyState = new Array("正在连接", "已建立连接", "正在关闭连接", "已关闭连接");
var host = 'ws://localhost:61413' +
window.location.pathname.replace('testWebSocket.html', 'EchoService') +
'?Name=liza';
webSocket = new WebSocket(host);
var message = document.getElementById("message");
message.innerHTML += "<p>Socket状态:" + readyState[webSocket.readyState] + "</p>";
webSocket.onopen = function () {
message.innerHTML += "<p>Socket状态:" + readyState[webSocket.readyState] + "</p>";
}
webSocket.onmessage = function (msg) {
message.innerHTML += "<p>接收信息:" + msg.data + "</p>";
}
webSocket.onclose = function () {
message.innerHTML += "<p>Socket状态:" + readyState[webSocket.readyState] + "</p>";
}
}
catch (exception) {
message.innerHTML += "<p>有错误发生</p>";
}
}
function send() {
var text = document.getElementById("text").value;
var message = document.getElementById("message");
if (text == "") {
message.innerHTML += "<p>请输入一些文字</p>";
return;
}
try {
webSocket.send(text);
message.innerHTML += "<p>发送数据:" + text + "</p>";
}
catch (exception) {
message.innerHTML += "<p>发送数据出错</p>";
}
document.getElementById("text").value = "";
}
function disconnect() {
webSocket.close();
}
</script>
<body>
<h1>WebSocket客户端示例</h1>
<div id="message"></div>
<p>请输入一些文字</p>
<input id="text" type="text">
<button id="connect" onclick="connect();">建立连接</button>
<button id="send" onclick="send();">发送数据</button>
<button id="disconnect" onclick="disconnect();">断开连接</button>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>WebSockets客户端示例</title>
</head>
<script>
var webSocket;
function connect() {
try {
var readyState = new Array("正在连接", "已建立连接", "正在关闭连接", "已关闭连接");
var host = 'ws://localhost:61413' +
window.location.pathname.replace('testWebSocket.html', 'EchoService') +
'?Name=liza';
webSocket = new WebSocket(host);
var message = document.getElementById("message");
message.innerHTML += "<p>Socket状态:" + readyState[webSocket.readyState] + "</p>";
webSocket.onopen = function () {
message.innerHTML += "<p>Socket状态:" + readyState[webSocket.readyState] + "</p>";
}
webSocket.onmessage = function (msg) {
message.innerHTML += "<p>接收信息:" + msg.data + "</p>";
}
webSocket.onclose = function () {
message.innerHTML += "<p>Socket状态:" + readyState[webSocket.readyState] + "</p>";
}
}
catch (exception) {
message.innerHTML += "<p>有错误发生</p>";
}
}
function send() {
var text = document.getElementById("text").value;
var message = document.getElementById("message");
if (text == "") {
message.innerHTML += "<p>请输入一些文字</p>";
return;
}
try {
webSocket.send(text);
message.innerHTML += "<p>发送数据:" + text + "</p>";
}
catch (exception) {
message.innerHTML += "<p>发送数据出错</p>";
}
document.getElementById("text").value = "";
}
function disconnect() {
webSocket.close();
}
</script>
<body>
<h1>WebSocket客户端示例</h1>
<div id="message"></div>
<p>请输入一些文字</p>
<input id="text" type="text">
<button id="connect" onclick="connect();">建立连接</button>
<button id="send" onclick="send();">发送数据</button>
<button id="disconnect" onclick="disconnect();">断开连接</button>
</body>
</html>

View Code

View Code

 

 



 同类别别的小说:何以运用HTML5的WebSocket达成网页与服务器的双工通讯(1)

 同种类别的小说:如何运用HTML伍的WebSocket实现网页与服务器的双工通讯(壹)

相关文章