之前一直在研究浏览器调用本地程序,但发现似乎只有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;//判断当前浏览器是否支持WebSocketif ('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版本

菜鸟谷歌浏览器打印组件技术分析相关推荐

  1. CAD组件技术分析——概述

    在计算机辅助设计领域,Autodesk有着举足轻重的作用,拥有较大的影响力.因此,基于Autodesk的产品输出的图纸(dwg)或模型(rvt)有很多的读写需求:相应地,各自组件技术也都支持这些专有格 ...

  2. WEB 打印的相关技术分析

    文/谢康 做Web开发的人员一定都会面临一个共同的难题,那就是打印.的确,相对于Windows桌面应用程序来讲,Web应用程序的打印有种种限制,技术人员在项目开发过程中经常会遇到用户这样或那样的需求. ...

  3. 【华为云技术分享】一行代码就能写一个日志打印组件,你信吗?为你揭晓LiteOS中日志打印组件的核心

    1. 做实验引发的思考 在学习LiteOS日志打印组件使用的时候,我记录了一篇博客:atiny_log | LiteOS 物联网操作系统中的日志打印组件使用分享,关于实验的具体内容,请阅读这篇博客. ...

  4. 中国人工智能学会通讯——机器人组件技术在智能制造系统中的应用

    摘要:随着工业4.0时代的到来,如何将传统工厂改造成为个性化.网络化.柔性生产的智能制造系统成为了当前的研究热点.本文从智能制造系统和智能机器人系统的相似性出发,构建了基于机器人组件技术的智能制造系统 ...

  5. 《纯技术分析阿里云OS和Android之间的关系》补充

    前面一份投稿的错误很抱歉,rom本身就找错了,用了一个AOSP-like的刷机包.好在这份内容错误的投稿多少起到了抛砖引玉的作用,当天晚上,就给出了正确的rom的分析<纯技术分析阿里云OS和An ...

  6. 什么是OpenMAX技术分析OpenMAX

    什么是OpenMAX技术分析OpenMAX OpenMAX是统一的抽象层,它允许访问否则需要供应商特定API的硬件. Broadcom的MMAL(多媒体抽象层API). 因此,OpenMAX允许使用此 ...

  7. 菜鸟实时数仓技术架构演进

    分享嘉宾:贾元乔 菜鸟 高级数据技术专家 内容来源:Flink Forward ASIA 出品平台:DataFunTalk 导读:在开源盛世的今天,实时数仓的建设已经有了较为成熟的方案,技术选型上也都 ...

  8. java超线程_超线程多核心下Java多线程编程技术分析

    在学习编程的过程中,我觉得不止要获得课本的知识,更多的是通过学习技术知识提高解决问题的能力,这样我们才能走在最前方,本文主要讲述超线程多核心下Java多线程编程技术分析,更多Java专业知识,广州疯狂 ...

  9. Microsoft .NET Pet Shop 4 架构与技术分析(转)

    Microsoft .NET Pet Shop 4 架构与技术分析 1.项目概述与架构分析微软刚推出了基于ASP.NET 2.0下的Pet Shop 4, 该版本有了一个全新的用户界面.是研究ASP. ...

  10. 【引用】内网安全数据保密技术分析与比较

    内网安全数据保密技术分析与比较 邹翔① 王志海②,李志涛② (①公安部第三研究所上海 200031: ②北京明朝万达科技有限公司,北京 100000) [摘要]本文通过对目前主要的内网安全数据保密关键 ...

最新文章

  1. 辗转相除法是求两个数的最大公约数的方法。
  2. Microsoft SQL Server学习(二)--数据库的语法
  3. 网络安全逐渐成为程序员的必备技能
  4. 02.改善深层神经网络:超参数调试、正则化以及优化 W3. 超参数调试、Batch Norm和程序框架(作业:TensorFlow教程+数字手势预测)
  5. 医生们团结一致,以增加对优质健康信息的访问
  6. Vista忘记密码如何登录?
  7. java swing container_Java Swing GUI学习(一)
  8. 编程题:字符串的指针引用。用指针法实现。功能:将字符串str2复制连接到str1...
  9. 关于Cocos2d-x的动作和动画
  10. 泛微oa系统什么框架_泛微OA ecology 二次开发实例 开发完整说明
  11. 基于Java GUI的资产管理系统的设计与实现
  12. matlab三次方程求根,如何用matlab求一元三次方程的最小正根?
  13. 酒店客房管理系统总结
  14. S3-s3cmd命令行工具使用
  15. 如何解决Worm.Win32.AutoRun.bqn(文件夹改exe病毒)
  16. 实时网速怎么看快慢_怎么测试下载速度(教你安全检测网速快慢)
  17. 【一文速通】机器学习样本不均衡/数据分布不同怎么办?
  18. Combo( 自定义下拉框) 组件
  19. 【一 DE1-SOC】quartus II下载程序步骤
  20. 算法 所有奇数长度子数组的和

热门文章

  1. 正则Regex中圆括号()方括号[]大括号{}的区别和用法
  2. chrome extensions快捷键shortcuts配置
  3. testcookie-nginx-module
  4. 海量数据实时计算系统在高并发互联网应用中的原理和实践
  5. Memory ordering in some architectures
  6. java中文api在线测试_万邑通开发者网站 - API在线测试
  7. java水电费收费系统_基于jsp的电费管理系统-JavaEE实现电费管理系统 - java项目源码...
  8. C/C++——C++中new与malloc的10点区别
  9. 支持全文搜索的桌面搜索工具
  10. GoC全教程(附各种下载、教程链接)