菜鸟谷歌浏览器打印组件技术分析

之前一直在研究浏览器调用本地程序,但发现似乎只有IE的OCX才能做到,谷歌浏览器虽然说有插件,但实现IE下OCX的功能却不太可能,忽然有一天,有个同事让我看一下菜鸟的打印组件,豁然开朗。

 菜鸟的打印组件竟然是在谷歌浏览器下实现了类似IE下的OCX技术,直接可以调用打印机,但分析发现,浏览器扩展根本没有安装新东西,说明菜鸟的打印组件根本不是通过谷歌浏览器的插件机制实现的。

无奈只能分析打印按钮的HMTL代码  

 没有行内脚本,猜测应该是根据类选择器printBtn J_printBtn 处理的点击事件,于是保存了一份网页,在下载中的中脚本中查看可能的点击事件,竟然在newWaybillPrint.js文件中找到了可能的代码

$("body").undelegate(".J_printBtn", "click").delegate(".J_printBtn", "click", function (e) {
				if (!J.printBtnFlag)
					return !1;
				var t = $(e.currentTarget),
				a = t.attr("data-id");
				"undefined" != typeof socket ? J.socketReadyState = socket.readyState : x._doConnect(),
				0 == J.socketReadyState ? (J.printBtnFlag = !0, m.Alert("webSocket\u8fde\u63a5\u6b63\u5728\u5efa\u7acb", "info")) : 2 == J.socketReadyState ? (J.printBtnFlag = !0, m.Alert("webSocket\u8fde\u63a5\u6b63\u5728\u8fdb\u884c\u5173\u95ed", "info")) : 3 == J.socketReadyState ? (J.printBtnFlag = !0, null == J.notInitOrOpenDialog && x._renderNotInitPrintDialog(), J.notInitOrOpenDialog.show()) : (J.printBtnFlag = !1, x._printViewDialog("single"), J.previewDialog.root.attr("data-curId", a), J.previewDialog.show())
			}),

在浏览器中调试,明显是压缩过的代码,但点击红色部分,可以格式化,并添加断点,调试,果然是。

 

 发现有一个    "undefined" != typeof socket ? J.socketReadyState = socket.readyState : x._doConnect(),

然后在分析socket,找到了

_doConnect: function () {
			var e = window.location,
			t = "",
			a = "";
			if ("https:" === e.protocol ? (t = "wss:", a = "13529") : (t = "ws:", a = "13528"), window.WebSocket)
				window.socket = new WebSocket(t + "//localhost:" + a), socket.onopen = function (e) {
					J.socketReadyState = e.target.readyState,
					x._doGetPrinters("123")
				},

竟然是通过WebSocket和本地的打印程序通讯,然后就可以调用本地资源了。感觉真的是太巧妙了。把打印程序作为WebSocket的服务端,这样就实现了通过浏览器调用本地资源的功能,实现了B/S,C/S巧妙结合的使用,充分合理利用了B/S,C/S的好处。

客户端浏览器和打印程序之间通过WebSocket进行交互

浏览器和菜鸟服务器是正常的BS程序

打印程序和和菜鸟服务器是正常的CS程序

简单的网页通讯代码

<!DOCTYPE html>
<html>
   <head>
      <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />  
 <style type="text/css">body * 
{
font-family:微软雅黑;font-size:14px
}
 </style> 
       <script type="text/javascript">


         var websocket = null;
     //判断当前浏览器是否支持WebSocket
     if ('WebSocket' in window) {
         websocket = new WebSocket("ws://localhost:8181");
     }
     else {
         alert('当前浏览器 Not support websocket')
     }
 
     //连接发生错误的回调方法
     websocket.onerror = function () {
         setMessageInnerHTML("WebSocket连接发生错误");
     };
 
     //连接成功建立的回调方法
     websocket.onopen = function () {
         //        setMessageInnerHTML("WebSocket连接成功");
         websocket.send("WebSocket连接成功");
     }
 
     //接收到消息的回调方法
     websocket.onmessage = function (event) {
         setMessageInnerHTML(event.data);
     }
 
     //连接关闭的回调方法
     websocket.onclose = function () {
         setMessageInnerHTML("WebSocket连接关闭");
     }
 
 
     //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
 
     window.onbeforeunload = function () {
 
         closeWebSocket();
 
     }
 
     //将消息显示在网页上
 
     function setMessageInnerHTML(innerHTML) {
 
         document.getElementById('message').innerHTML +="收到消息:"+ innerHTML + '<br/>';
 
     }
 
     function closeWebSocket() {
 
         websocket.close();
 
     }
 
 
     function clear(){
         document.getElementById('message').innerHTML="";
     }
 
     //发送消息
 
     function send() {
 
         var message = document.getElementById('text').value;
 
         websocket.send(message);
 
     }
</script> 
</head>
   <body  style="padding:0px;width:1015px">
       <button onclick="closeWebSocket()">关闭WebSocket连接</button>
       <button onclick="clear()">清空</button>
       <hr />
       <input type="text" id="text" />
       <button onclick="send()">发送消息</button>
       <div id="message"></div>
</body>
</html>

使用Csharp插件Fleck编写的简单的模拟打印程序

using Fleck;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace WindowsFormsWebSocket
{
    public partial class Form1 : Form
    {
        WebSocketServer server = null;
      //  IWebSocketConnection client = null;
        Dictionary<Guid, IWebSocketConnection> dic = new Dictionary<Guid, IWebSocketConnection>();
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            server = new WebSocketServer("ws://127.0.0.1:8181");
            server.RestartAfterListenError = true;
            server.Start(socket =>
            {
                socket.OnOpen = () => OnOpen(socket);
                socket.OnClose = () => OnClose(socket);
                socket.OnMessage = m => OnMessage(socket, m);
            });
        }

        private void OnMessage(IWebSocketConnection socket, string m)
        {
            MessageBox.Show("收到客户端消息:"+m);
           // throw new NotImplementedException();
        }

        private void OnClose(IWebSocketConnection socket)
        {
            Guid id = socket.ConnectionInfo.Id;
            if(dic.ContainsKey(id))
            {
                IWebSocketConnection sond= dic[id];
                sond.Close();
                dic.Remove(id);
            }         
            MessageBox.Show("OnClose");
        }

        private void OnOpen(IWebSocketConnection socket)
        {
            Guid id = socket.ConnectionInfo.Id;
            if (dic.ContainsKey(id))
            {
                IWebSocketConnection sond = dic[id];
                sond.Close();
                dic.Remove(id);
            }
            else
            {
                dic[id] = socket;
            }          
        }

        private void button1_Click(object sender, EventArgs e)
        {   
           string text= textBox1.Text;
            foreach(var i in dic)
            {
                IWebSocketConnection sond = i.Value;
                sond.Send(text);
            }          
        }
    }
}

.NET 的 WebSocket 开发包比较(转)

C# 实现WebSocket服务端实例

Writing a WebSocket server in C#

The simple WebSocket application in ASP.NET

在IIS上搭建WebSocket服务器

C# Websocket Implementation

史上最全Web端即时通讯技术原理详解

WebSocket

HTML5 WebSocket

关于websocket兼容IE版本

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值