• 采用自定义协议代替OCX组件


    事情起源:公司视频播放一直是采用的嵌入浏览器组件实现视频的预览回放等功能。这种实现方式要求客户使用IE浏览器。

    最近上线项目使用Html 5开发,要求IE11。项目中使用了视频播放功能,如果全部升级到IE11问题多,工作量大。

    存在的主要问题:

    有些系统开发较早,不能在IE11上运行。

    部分客户电脑配置低还在使用XP。因为视频播放插件要求IE浏览器,所以支持H5的chrome,firefox等浏览器又不符合要求。

    修改项目兼容低版本浏览器那是不可能的,只能修改视频播放插件。

    1、视频插件改为 应用程序 安装到客户计算机,使用浏览器自定义协议启动。这样解决了浏览器兼容问题,几乎所有浏览器都支持自定义协议。

    测试用例:注册表写入以下内容就可以启动 d:myapp.exe

    Windows Registry Editor Version 5.00
    [HKEY_CLASSES_ROOTmyapp]
    @="URL:AutoHotKey myapp Protocol"
    "URL Protocol"=""
    [HKEY_CLASSES_ROOTmyappDefaultIcon]
    @="myapp.exe,1"
    [HKEY_CLASSES_ROOTmyappshell]
    [HKEY_CLASSES_ROOTmyappshellopen]
    [HKEY_CLASSES_ROOTmyappshellopencommand]
    @=""d:\myapp.exe" "%1""

    javascript 点击启动myapp.exe

    function LaunchApp() {
    try {

    window.location = 'myapp://,start';

    }
    catch (ex) {
    errMsg = "启动 myapp 报错. ";
    alert(errMsg);
    }
    return;
    };

    2、如何判断用户有没安装视频应用呢??

    网上搜索了一下,看着比较靠谱的:

    https://www.cnblogs.com/tangjiao/p/9646855.html

    这个实现方案是有缺陷,在chrome浏览器通过计时器和当前窗体失去焦点来判段。

    计时器设置时间短路了,程序在配置低的电脑上会失败。

    计时器设置时间长了,chrome上切换tab页就失去焦点,认为已经安装。

    通过观察百度云盘的运行方式,得到启发。百度云盘也是采用了自定义协议。启动yundetectservice.exe 监听10000端口,

    猜测web页面和yundetectservice.exe进行了通信。yundetectservice.exe启动成功会通知web页面。

    3、采用 websocket 实现,视频应用启动的时候监听某端口等待 web页面连接,如果一定时间内连接成功就认为已经安装了插件。

    web页面websocket连接的例子网上比较多。

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
    <html>
        <head>
            <title>Test</title>
            <script type="text/javascript" src="jquery.js"></script>
            <script type="text/javascript">
                var noSupportMessage = "Your browser cannot support WebSocket!";
                var ws;
    
                function appendMessage(message) {
                    $('body').append(message);
                }
    
                function connectSocketServer() {
                    var support = "MozWebSocket" in window ? 'MozWebSocket' : ("WebSocket" in window ? 'WebSocket' : null);
    
                    if (support == null) {
                        appendMessage("* " + noSupportMessage + "<br/>");
                        return;
                    }
    
                    appendMessage("* Connecting to server ..<br/>");
                    // create a new websocket and connect
                    ws = new window[support]('ws://localhost:12345/');
    
                    // when data is comming from the server, this metod is called
                    ws.onmessage = function (evt) {
                        appendMessage("# " + evt.data + "<br />");
                    };
    
                    // when the connection is established, this method is called
                    ws.onopen = function () {
                        appendMessage('* Connection open<br/>');
                        $('#messageInput').attr("disabled", "");
                        $('#sendButton').attr("disabled", "");
                        $('#connectButton').attr("disabled", "disabled");
                        $('#disconnectButton').attr("disabled", "");
                    };
    
                    // when the connection is closed, this method is called
                    ws.onclose = function () {
                        appendMessage('* Connection closed<br/>');
                        $('#messageInput').attr("disabled", "disabled");
                        $('#sendButton').attr("disabled", "disabled");
                        $('#connectButton').attr("disabled", "");
                        $('#disconnectButton').attr("disabled", "disabled");
                    }
                }
    
                function sendMessage() {
                    if (ws) {
                        var messageBox = document.getElementById('messageInput');
                        ws.send(messageBox.value);
                        messageBox.value = "";
                    }
                }
    
                function disconnectWebSocket() {
                    if (ws) {
                        ws.close();
                    }
                }
    
                function connectWebSocket() {
                    connectSocketServer();
                }
    
                window.onload = function () {
                    $('#messageInput').attr("disabled", "disabled");
                    $('#sendButton').attr("disabled", "disabled");
                    $('#disconnectButton').attr("disabled", "disabled");
                }
        
        </script>
        </head>
        <body>
            <input type="button" id="connectButton" value="Connect" onclick="connectWebSocket()"/> <input type="button" id="disconnectButton" value="Disconnect" onclick="disconnectWebSocket()"/> <input type="text" id="messageInput" /> <input type="button" id="sendButton" value="Send" onclick="sendMessage()"/> <br />
        </body>
    </html>

    实现websocket服务也有很多方法。

    开源的有,SuperWebSocket,Fleck,WebSocketListener,websocket-sharp 等。

    DotNet 高版本自带了System.Net.WebSockets;

    因为功能简单,仅仅是接受连接请求,所以采用dontnet自带的,不用引入多余的类库。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Net.WebSockets;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    
    namespace TestServer
    {
        class Program
        {
            static void Main(string[] args)
            {
                RunEchoServer().Wait();
            }
            private static async Task RunEchoServer()
            {
                HttpListener listener = new HttpListener();
                listener.Prefixes.Add("http://localhost:12345/");
                listener.Start();
                Console.WriteLine("Started");
                while (true)
                {
                    HttpListenerContext context = listener.GetContext();
                    //
                    if (!context.Request.IsWebSocketRequest)
                    {
                        context.Response.Close();
                        continue;
                    }
                    //
                    Console.WriteLine("Accepted");
                    //
                    var wsContext = await context.AcceptWebSocketAsync(null);
                    var webSocket = wsContext.WebSocket;
                    //
                    byte[] buffer = new byte[1024];
                    WebSocketReceiveResult received = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
    
                    while (received.MessageType != WebSocketMessageType.Close)
                    {
    
                        Console.WriteLine($"Echoing {received.Count} bytes received in a {received.MessageType} message; Fin={received.EndOfMessage}");
                        // Echo anything we receive
                        await webSocket.SendAsync(new ArraySegment<byte>(buffer, 0, received.Count), received.MessageType, received.EndOfMessage, CancellationToken.None);
    
                        received = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
                    }
    
                    await webSocket.CloseAsync(received.CloseStatus.Value, received.CloseStatusDescription, CancellationToken.None);
    
                    webSocket.Dispose();
                    Console.WriteLine("Finished");
                }
            }
        }
    }

    至此,通过自定义协议和websocket 解决了视频插件的问题。

  • 相关阅读:
    VMware rhel 7 网卡绑定
    VMware 克隆虚拟机后网卡无法启动
    rhel7 批量新建和删除用户
    2019.3.27 Linux 学习
    20180313前端笔试
    javascript中的一些问题
    flex布局学习笔记(阮一峰flex布局教程)
    个推面试总结
    笔试题目整理
    @JsonFormat与@DateTimeFormat注解的使用
  • 原文地址:https://www.cnblogs.com/onecool/p/10043607.html
Copyright © 2020-2023  润新知