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


    今天的文章来说明如何在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源代码哦。感谢支持

  • 相关阅读:
    java、el表达式中保留小数的方法
    EL表达式取整数或者取固定小数位数的简单实现
    Spring框架学习之第8节
    shell脚本接收输入
    awk除去重复行
    awk过滤统计不重复的行
    Spring框架学习之第7节
    jsp中利用checkbox进行批量删除
    javaScript解决Form的嵌套
    Spring框架学习之第6节
  • 原文地址:https://www.cnblogs.com/dathlin/p/12303098.html
Copyright © 2020-2023  润新知