WebSocket:双工通讯

一直好奇,所以简单总结一下

WebSocket 是 HTML5 一种新的协议。它实现了浏览器与服务器全双工通信,能更好的节省服务器资源和带宽并达到实时通讯,它建立在 TCP 之上,同 HTTP 一样通过 TCP 来传输数据,但是它和 HTTP 最大不同是:

  • WebSocket 是一种双向通信协议,在建立连接后,WebSocket 服务器和 Browser/Client Agent 都能主动的向对方发送或接收数据,就像 Socket 一样;
  • WebSocket 需要类似 TCP 的客户端和服务器端通过握手连接,连接成功后才能相互通信。

 

      WebSocket 的实现分为客户端和服务端两部分,客户端(通常为浏览器)发出 WebSocket 连接请求,服务端响应,实现类似 TCP 握手的动作,从而在浏览器客户端和 WebSocket 服务端之间形成一条 HTTP 长连接快速通道。两者之间后续进行直接的数据互相传送,不再需要发起连接和相应。

PS:一开始一直按照教程用.net core 2.0 调试,但是到json解析这一步报错,说版本不匹配。到存储过程执行这一步,直接没有 SqlParameter[]。直接不会了,只好,重新创建了一个控制台程序,然后手工引入Fleck组件,然后把前面的代码复制过来,json就用以前的办法,存储过程也用SqlParameter[],直接正常执行,那就好,总算可以随便使用了。

服务端

using Fleck;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace web_socket
{
    class Program
    {
        //客户端url以及其对应的Socket对象字典
        private static IDictionary<string, IWebSocketConnection> dic_Sockets = new Dictionary<string, IWebSocketConnection>(); 
       
        static void Main(string[] args)
        {
            //创建
            WebSocketServer server =
                new WebSocketServer("ws://192.168.3.95:1235")
                {
                    //出错后进行重启
                    RestartAfterListenError = true
                };//监听所有的的地址

            //开始监听
            server.Start(socket =>
            {
                socket.OnOpen = () =>   //连接建立事件
                {
                    //获取客户端网页的url
                    string clientUrl = socket.ConnectionInfo.ClientIpAddress + ":" + socket.ConnectionInfo.ClientPort;
                    dic_Sockets.Add(clientUrl, socket);
                    Console.WriteLine(DateTime.Now.ToString() + "|服务器:和客户端网页:" + clientUrl + " 建立WebSock连接!");
                };
                socket.OnClose = () =>  //连接关闭事件
                {
                    string clientUrl = socket.ConnectionInfo.ClientIpAddress + ":" + socket.ConnectionInfo.ClientPort;
                    //如果存在这个客户端,那么对这个socket进行移除
                    if (dic_Sockets.ContainsKey(clientUrl))
                    {
                        //注:Fleck中有释放
                        //关闭对象连接 
                        //if (dic_Sockets[clientUrl] != null)
                        //{
                        //dic_Sockets[clientUrl].Close();
                        //}
                        dic_Sockets.Remove(clientUrl);
                    }
                    Console.WriteLine(DateTime.Now.ToString() + "|服务器:和客户端网页:" + clientUrl + " 断开WebSock连接!");
                };
                socket.OnMessage = message =>  //接受客户端网页消息事件
                {
                    string clientUrl = socket.ConnectionInfo.ClientIpAddress + ":" + socket.ConnectionInfo.ClientPort;
                    Console.WriteLine(DateTime.Now.ToString() + "|服务器:【收到】来客户端网页:" + clientUrl + "的信息:\n" + message);
                    string res = "";
                    res = websocket.BaseClass.SelectMethod.GetResult(message);  //根据消息返回各种业务
                    if (res != "")
                    {
                        socket.Send(res);
                    }
                    else
                    {
                        socket.Send("你好" + clientUrl + ",我已经收到你的消息!");
                    }
                };
            });

            //放个计时器,进行任务轮询
            Timer t = new Timer(10000);
            t.Enabled = true;
            t.Elapsed += T_Elapsed;

            Console.ReadKey();
            foreach (var item in dic_Sockets.Values)
            {
                if (item.IsAvailable == true)
                {

                    item.Send("服务器消息:" + DateTime.Now.ToString());
                }
            }
            Console.ReadKey();

            //关闭与客户端的所有的连接
            foreach (var item in dic_Sockets.Values)
            {
                if (item != null)
                {
                    item.Close();
                }
            }

            Console.ReadKey();
        }

        private static void T_Elapsed(object sender, ElapsedEventArgs e)
        {
            Console.WriteLine("hello timer! 2秒一次");
            foreach (var item in dic_Sockets)
            {
                //这里做主动业务
                Console.WriteLine("链接:{0},对象:{1}", item.Key, item.Value);  
            }
        }
    }
}

客户端

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>WebSocket测试</title>
		<style>
			.div1
			{
				height:88px;   
				width:173px;
				border:1px solid blue;
				margin:auto;
			}
			h4
			{
				margin:auto;
			}
		</style>
		<script>
			var webSocket = {};
			var connect_flag=false;
			//创建websockt			
			function CreateWebSocket() {
				webSocket = new WebSocket("ws://192.168.3.95:1235");
				webSocket.onopen = WebSokectOnOpen;
				webSocket.onmessage = WebSocketOnMessage;
				webSocket.onclose = WebSocketOnClose;
				// webSocket.onerror = WebSocketOnError;
			};
			
			//建立连接事件
			function WebSokectOnOpen() {
				console.log("已经打开连接!");
				webSocket.send(LoginData());								
			};
			
			function LoginData(){	
				connect_flag=true;
				return '{"Userno":"0001","Msg":"hello","Sign":"1234","Method":"sqldata"}';
			}

			//监听事件
			function WebSocketOnMessage(event) {
				//监听来自客户端的数据
				console.log(event.data);
			};

			function WebSocketOnClose() {
				//监听来自客户端的数据
				console.log('和服务器断开连接');	
				setTimeout(function () {
					console.log('尝试重新连接服务器......');	
					CreateWebSocket();	//这样重新连接会造成很多的 重新连接 判断													
					console.log('状态:'+connect_flag+' 连接服务器失败,5秒后尝试......');					
				}, 5000);											
			};
						
			function WebSocketOnError(){
				// 如果连接失败,发送、接收数据失败或者处理数据出现错误,browser 会触发 onerror 消息;
				console.log('====================发生错误====================')
			};

			//发送事件
			function WebSocketSendMsg() {
				//获取text中的值
				var text = document.getElementById("Text1").value;
				//发送到服务器
				webSocket.send(text);
			};
		</script>
	</head>
	<body onload="CreateWebSocket()">
    <div class="div1">
        <h4>WebSocket测试</h4>
        <h4>By:haojun</h4>
        <input type="text" id="Text1" />
        <input type="button" onclick="WebSocketSendMsg()" value="发送数据" />
    </div>
</body>
</html>

服务端直接生成exe程序,启动结果如下

客户端运行结果

和服务器断开连接
web_socket.html:52 尝试重新连接服务器......
web_socket.html:54 状态:true 连接服务器失败,5秒后尝试......
web_socket.html:33 已经打开连接!
web_socket.html:45 {"status":"1","msg":"OK","result":"{"data":{"status":"1","message":"","allpage":"2","pagelength":"8","data":[{"id":"10","card_no":"12BOuU5qs/MI+lz+sCejM94/WHsQdIW72Q2002","card_money":"200.00","create_date":"2019-02-16 11:22:03","create_user":"测试","sell_flag":"预销售","sell_date":"1900-01-01 00:00:00","update_user":"测试","sys_date":"2019-02-16 11:22:03.280"},{"id":"9","card_no":"12BOuU5qs/MI+lz+sCejM94/WHsQdIW72Q2001","card_money":"200.00","create_date":"2019-02-16 11:21:57","create_user":"测试","sell_flag":"预销售","sell_date":"2019-02-18 15:20:50","update_user":"测试","sys_date":"2019-02-16 11:21:57.143"},{"id":"8","card_no":"12BOuU5qs/MI+lz+sCejM94/WHsQdIW72Q2007","card_money":"700.00","create_date":"2019-02-16 11:21:48","create_user":"测试","sell_flag":"预销售","sell_date":"1900-01-01 00:00:00","update_user":"测试","sys_date":"2019-02-16 11:21:48.590"},{"id":"7","card_no":"12BOuU5qs/MI+lz+sCejM94/WHsQdIW72Q2006","card_money":"502.00","create_date":"2019-02-16 11:21:01","create_user":"测试","sell_flag":"已销售","sell_date":"2019-02-20 16:45:31","update_user":"测试","sys_date":"2019-02-18 15:27:24.923"},{"id":"6","card_no":"12BOuU5qs/MI+lz+sCejM94/WHsQdIW72Q2005","card_money":"500.00","create_date":"2019-02-16 11:19:22","create_user":"测试","sell_flag":"已销售","sell_date":"2019-02-20 16:45:26","update_user":"测试","sys_date":"2019-02-20 16:45:13.107"},{"id":"5","card_no":"12BOuU5qs/MI/m1qmoIH6gZg==9013","card_money":"204.00","create_date":"2019-02-16 11:18:55","create_user":"测试","sell_flag":"待命","sell_date":"2019-02-18 15:30:50","update_user":"测试","sys_date":"2019-02-18 15:26:06.367"},{"id":"4","card_no":"12BOuU5qs/MI96TMhSb7BMFXLCf3UTQ8Q+6666","card_money":"600.00","create_date":"2019-02-16 11:18:23","create_user":"测试","sell_flag":"待命","sell_date":"1900-01-01 00:00:00","update_user":"测试","sys_date":"2019-02-16 11:18:23.607"},{"id":"3","card_no":"12BOuU5qs/MI9TNLZSde8dypYcdUpqwlux2155","card_money":"300.00","create_date":"2019-02-16 11:17:29","create_user":"测试","sell_flag":"预销售","sell_date":"1900-01-01 00:00:00","update_user":"测试","sys_date":"2019-02-18 15:18:26.960"}]}}"}

 

官方 https://www.ibm.com/developerworks/cn/java/j-lo-WebSocket/

大神 阮一峰  http://www.ruanyifeng.com/blog/2017/05/websocket.html

.net core2.0 官方:   https://docs.microsoft.com/zh-cn/dotnet/core/tools/dotnet-build?tabs=netcore2x

.net core2.0 是什么:https://blog.csdn.net/QingHeShiJiYuan/article/details/78184543

.net core2.0 打包: http://www.cnblogs.com/TianFang/p/8370804.html

 

 

转载于:https://my.oschina.net/qingqingdego/blog/3021506

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值