如何使用HTML5的WebSocket实现网页与服务器的双工通信(二)
程序员文章站
2022-04-06 12:03:19
本系列服务端双工通信包括两种实现方式:一、使用Socket构建;二、使用WCF构建。本文为使用WCF构建服务端的双工通信,客户端同样使用Html5的WebSocket技术进行调用 ......
本系列服务端双工通信包括两种实现方式:一、使用Socket构建;二、使用WCF构建。本文为使用WCF构建服务端的双工通信,客户端同样使用Html5的WebSocket技术进行调用。
一、创建WCF服务库Wcf.Duplex.Library:
1.定义协议的服务接口:
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 }
注意:
OperationContract中的Action,一定要设置。
IWebSocketEcho接口中:只能定义一个OperationContract(IsOneWay = true, Action = "*")方法入口,否则使用WebSocket连接时会报错
IWebSocketEchoCallback 回调接口中:可以定义多个OperationContract(IsOneWay = true, Action = "*")方法
2.实现服务协议,并定义一个时钟,定时调用回调方法,发送信息给客户端:
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 }
二.新建WEB项目,在项目中引用第一步建立的WCF服务库Wcf.Duplex.Library。
1.打开Global.asax.cs的文件,在Application_Start增加以下代码:
RouteTable.Routes.Add(new ServiceRoute("EchoService",new ServiceHostFactory(),typeof(EchoService)));
说明:增加服务路由的时候,路由前缀可以随便设置;ServiceType,需要设置为WCF服务库的EchoService类。
2.配置WEB.Config:
<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>
3.在当前项目中增加页面testWebSocket.html,使用WebSocket调用服务
<!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>
同系列其他文章:
上一篇: cc.Component
下一篇: 七牛的fops可以使用魔术变量吗?