文档章节

C# 实现 websocket 服务器 发送客户端网页前端数据,C#和网页前端通信

o
 osc_x2c17gwy
发布于 02/13 12:18
字数 1490
阅读 19
收藏 0

行业解决方案、产品招募中!想赚钱就来传!>>>

今天的文章来说明如何在C#里构建我们自己的websocket服务器,已经客户端,以及如何发送数据给客户端,如何实现订阅的操作,如何实现应答模式的操作。ok,废话不多说,直接进入正题:

 

本库的demo源代码地址:https://github.com/dathlin/HslCommunication

如果想要联系作者,请访问官网:  http://www.hslcommunication.cn/

 

联系作者及加群方式:http://www.hslcommunication.cn/Cooperation 

 

在Visual Studio 中的NuGet管理器中可以下载安装,也可以直接在NuGet控制台输入下面的指令安装:

 

1
Install-Package HslCommunication

  

 如果需要教程:Nuget安装教程:http://www.cnblogs.com/dathlin/p/7705014.html

 

using HslCommunication.WebSocket;
using HslCommunication;

  

测试的websocket服务端界面如下:

 

 

 我们的客户端如下的信息:

 

 

 

好了,我们来学习如何开发websocket的服务器,其实很简单,实例化,启动服务器就可以了。就好比下面的代码,绑定了一个事件的回调地址,我们把数据显示出来即可

private WebSocketServer wsServer;

        private void button1_Click( object sender, EventArgs e )
        {
            try
            {
                wsServer = new WebSocketServer( );
                wsServer.OnClientApplicationMessageReceive += WebSocket_OnClientApplicationMessageReceive;
                wsServer.ServerStart( 1883 );
                MessageBox.Show( "Start Success" );
            }
            catch (Exception ex)
            {
                MessageBox.Show( "Start Failed : " + ex.Message );
            }
        }
        private void WebSocket_OnClientApplicationMessageReceive( WebSocketSession session, WebSocketMessage message )
        {
            Invoke( new Action( ( ) =>
            {
                if(!isStop)
                    textBox8.AppendText( $"OpCode:[{message.OpCode}] Mask:[{message.HasMask}] Payload:[{Encoding.UTF8.GetString( message.Payload )}]" + Environment.NewLine );
            } ) );
            }
        }

 

我们新增一个按钮,用来发送数据到客户端的

wsServer.PublishAllClientPayload( "测试的数据信息" );

好了,我们目前可以测试了

 

 

客户端收到了数据内容,我们现在来看看,是否推送给了网页端,为此我们需要编写一个简单的网页。新建一个html文件,打开记事本,写入下面的代码

<!DOCTYPE HTML>
<html>
   <head>
   <meta charset="utf-8">
   <title>hsl websocket测试</title>
      <script type="text/javascript">
         function WebSocketTest()
         {
            if ("WebSocket" in window)
            {
               // 打开一个 web socket
               var ws = new WebSocket("ws://127.0.0.1:1883");
               ws.onopen = function()
               {
                  console.log("已经打开...");
               };
               ws.onmessage = function (evt) 
               { 
                  var received_msg = evt.data;
                  console.log(received_msg);
               };
            }
            
            else
            {
				console.log("您的浏览器不支持 WebSocket!");
            }
         }
      </script>
   </head>
   <body>
      <div id="sse">
         <a href="javascript:WebSocketTest()">运行 WebSocket</a>
      </div>
      
   </body>
</html>

  

 然后我们运行起来,我这使用了谷歌的浏览器运行了这个网页的信息。

 

 

当然了,客户端和网页也可以直接发送数据给C#的服务器后台。我们现在看看web端的数据是如何发送的

ws.send("发送数据");

  我们看到发送数据非常的简单。

 

我们已经看过了web端的数据通信方式,我们再来看看C#端的客户端是如何操作的

private WebSocketClient wsClient;

		private void button1_Click( object sender, EventArgs e )
		{
			wsClient = new WebSocketClient( "127.0.0.1", 1883 );
              wsClient.OnClientApplicationMessageReceive += WebSocket_OnWebSocketMessageReceived; OperateResult connect = wsClient.ConnectServer( ); if (connect.IsSuccess) { MessageBox.Show( StringResources.Language.ConnectServerSuccess ); } else { MessageBox.Show( connect.Message ); } } private void WebSocket_OnWebSocketMessageReceived( WebSocketMessage message ) { try { Invoke( new Action( ( ) => { string msg = Encoding.UTF8.GetString( message.Payload ); textBox8.AppendText( msg + Environment.NewLine ); } ) ); } catch { } }

客户端发送数据也是很简单的。

private void button3_Click( object sender, EventArgs e )
		{
			OperateResult send = wsClient.SendServer(  textBox4.Text );

			if (!send.IsSuccess) MessageBox.Show( "Send Failed:" + send.Message );
		}

  

 

 

讲完了上述,再来讲讲订阅。从websocket协议来看,其实没有订阅的功能,这个都是二次开发实现的。在hsl的服务器中,允许客户端请求的时候携带header,来表示当前的订阅信息。

比如我想订阅A,那么header就要增加 

HslSubscribes: A

  

服务器端就可以使用下面的方法来发布订阅操作了

wsServer.PublishClientPayload( "A", "1234" );

  

就会只给当前订阅的客户端发送数据。当然这种方式比较不好,无法动态调整订阅的信息,而且对于web端原生的websocket,也不太好集成、那我们可以使用二次开发的方式实现。比如服务器端,根据客户端发来的数据进行动态添加订阅。

private void WebSocket_OnClientApplicationMessageReceive( WebSocketSession session, WebSocketMessage message )
		{
			Invoke( new Action( ( ) =>
			{
				if(!isStop)
					textBox8.AppendText( $"OpCode:[{message.OpCode}] Mask:[{message.HasMask}] Payload:[{Encoding.UTF8.GetString( message.Payload )}]" + Environment.NewLine );
			} ) );

			// 假设发来的数据是订阅的主题。那我们可以动态添加
			session.AddTopic( Encoding.UTF8.GetString( message.Payload ) );

		}

  

当然也可以动态移除,需要对payload数据进行约定了。好了,最后介绍下,同步访问机制。hsl的websocket支持同步访问机制,客户端在标记自己的请求为同步访问后。服务器端发布数据的时候自动过滤所有的同步客户端。同步客户端的意思是,客户端发送数据给客户端,并等待服务器的返回。

private void WebSocket_OnClientApplicationMessageReceive( WebSocketSession session, WebSocketMessage message )
		{
			Invoke( new Action( ( ) =>
			{
				if(!isStop)
					textBox8.AppendText( $"OpCode:[{message.OpCode}] Mask:[{message.HasMask}] Payload:[{Encoding.UTF8.GetString( message.Payload )}]" + Environment.NewLine );
			} ) );

			// 应答客户端连接的情况下是需要进行返回数据的,此处演示返回的是原始的数据,追加一个随机数,你可以自己根据业务来决定返回什么数据
			if (session.IsQASession)
			{
				wsServer.SendClientPayload( session, Encoding.UTF8.GetString( message.Payload ) + random.Next( 1000, 10000 ) );
			}
		}

  

此处的示例就是

private void WebSocket_OnClientApplicationMessageReceive( WebSocketSession session, WebSocketMessage message )
		{
			Invoke( new Action( ( ) =>
			{
				if(!isStop)
					textBox8.AppendText( $"OpCode:[{message.OpCode}] Mask:[{message.HasMask}] Payload:[{Encoding.UTF8.GetString( message.Payload )}]" + Environment.NewLine );
			} ) );

			// 应答客户端连接的情况下是需要进行返回数据的,此处演示返回的是原始的数据,追加一个随机数,你可以自己根据业务来决定返回什么数据
			if (session.IsQASession)
			{
				wsServer.SendClientPayload( session, Encoding.UTF8.GetString( message.Payload ) + random.Next( 1000, 10000 ) );
			}
		}

 

当然了,你也可以直接认定所有的客户端,都是同步网络。这样的话,就不需要判断了、

private void WebSocket_OnClientApplicationMessageReceive( WebSocketSession session, WebSocketMessage message )
		{
			Invoke( new Action( ( ) =>
			{
				if(!isStop)
					textBox8.AppendText( $"OpCode:[{message.OpCode}] Mask:[{message.HasMask}] Payload:[{Encoding.UTF8.GetString( message.Payload )}]" + Environment.NewLine );
			} ) );

			// 应答客户端连接的情况下是需要进行返回数据的,此处演示返回的是原始的数据,追加一个随机数,你可以自己根据业务来决定返回什么数据
			//if (session.IsQASession)
			//{
				wsServer.SendClientPayload( session, Encoding.UTF8.GetString( message.Payload ) + random.Next( 1000, 10000 ) );
			//}
		}

  

实际看业务需求了。

我们来看看同步的客户端操作

private WebSocketQANet wsClient;

		private void button1_Click( object sender, EventArgs e )
		{
			wsClient = new WebSocketQANet( "127.0.0.1", 1883 );
			OperateResult connect = wsClient.ConnectServer( );
			if (connect.IsSuccess)
			{
				MessageBox.Show( StringResources.Language.ConnectServerSuccess );
			}
			else
			{
				MessageBox.Show( StringResources.Language.ConnectedFailed + connect.ToMessageShowString( ) );
			}
		}

  

 

然后就可以直接访问了

OperateResult<string> read = wsClient.ReadFromServer(  "123" );

			if (read.IsSuccess)
			{
				string msg = read.Content;
                        }
                        else
                        {
                            // 失败
                        }

  

好了,更多的详细内容可以参考demo源代码哦。感谢支持

 

o
粉丝 0
博文 500
码字总数 0
作品 0
私信 提问
加载中
请先登录后再评论。
Netty那点事(三)Channel与Pipeline

Channel是理解和使用Netty的核心。Channel的涉及内容较多,这里我使用由浅入深的介绍方法。在这篇文章中,我们主要介绍Channel部分中Pipeline实现机制。为了避免枯燥,借用一下《盗梦空间》的...

黄亿华
2013/11/24
2W
22
访问安全控制解决方案

本文是《轻量级 Java Web 框架架构设计》的系列博文。 今天想和大家简单的分享一下,在 Smart 中是如何做到访问安全控制的。也就是说,当没有登录或 Session 过期时所做的操作,会自动退回到...

黄勇
2013/11/03
3.5K
6
用vertx实现高吞吐量的站点计数器

工具:vertx,redis,mongodb,log4j 源代码地址:https://github.com/jianglibo/visitrank 先看架构图: 如果你不熟悉vertx,请先google一下。我这里将vertx当作一个容器,上面所有的圆圈要...

jianglibo
2014/04/03
4.1K
3
SQLServer实现split分割字符串到列

网上已有人实现sqlserver的split函数可将字符串分割成行,但是我们习惯了split返回数组或者列表,因此这里对其做一些改动,最终实现也许不尽如意,但是也能解决一些问题。 先贴上某大牛写的s...

cwalet
2014/05/21
9.6K
0
树莓派(Raspberry Pi):完美的家用服务器

自从树莓派发布后,所有在互联网上的网站为此激动人心的设备提供了很多有趣和具有挑战性的使用方法。虽然这些想法都很棒,但树莓派( RPi )最明显却又是最不吸引人的用处是:创建你的完美家用...

异次元
2013/11/09
6.4K
8

没有更多内容

加载失败,请刷新页面

加载更多

React Native常用第三方组件汇总

react-native-animatable 动画 react-native-carousel 轮播 react-native-countdown 倒计时 react-native-device-info 设备信息 react-native-fileupload 文件上传 react-native-icons 图标 ......

mdoo
28分钟前
8
0
troubleshoot之:用control+break解决线程死锁问题

简介 如果我们在程序中遇到线程死锁的时候,该怎么去解决呢? 本文将会从一个实际的例子出发,一步一步的揭开java问题解决的面纱。 死锁的代码 写过java多线程程序的人应该都知道,多线程中一...

flydean
28分钟前
19
0
无法打开与身份验证代理的连接 - Could not open a connection to your authentication agent

问题: I am running into this error of: 我遇到以下错误: $ git push heroku masterWarning: Permanently added the RSA host key for IP address '50.19.85.132' to the list of known ......

法国红酒甜
45分钟前
25
0
Trivy

Trivy 是一个面向镜像的漏洞检测工具,具备如下特点: 开源 免费 易用 准确度高 CI 友好 相对于老前辈 Clair,Trivy 的使用非常直观方便,适用于更多的场景。 下面是官方出具的对比表格: 扫...

LitStone
今天
7
0
在UITableView中使用自动布局以获取动态单元格布局和可变的行高

问题: 如何在表格视图的UITableViewCell使用自动布局,以使每个单元格的内容和子视图确定行高(自身/自动),同时保持流畅的滚动性能? 解决方案: 参考一: https://stackoom.com/questio...

技术盛宴
今天
13
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部