ホームページ  >  記事  >  ウェブフロントエンド  >  [転送] HTML5 を使用してリアルタイム Web アプリケーションを構築する WebSocket_html/css_WEB-ITnose

[転送] HTML5 を使用してリアルタイム Web アプリケーションを構築する WebSocket_html/css_WEB-ITnose

WBOY
WBOYオリジナル
2016-06-24 11:47:551014ブラウズ

HTML5 WebSocket の紹介と実践演習

この記事では主に HTML5 WebSocket の原理とそれがリアルタイム Web 開発にもたらす革新的なイノベーションを紹介し、WebSocket サーバーの事例を通じて WebSocket の利点を十分に実証します強力で使いやすいクライアント。

次世代の Web 標準として、HTML5 には、Canvas、ローカル ストレージ、マルチメディア プログラミング インターフェイス、WebSocket など、多くの魅力的な新機能が備わっています。その中でも特に開発者の注目を集めているのが「WebのTCP」とも呼ばれるWebSocketです。 WebSocket の出現により、ブラウザが Socket をサポートできるようになり、ブラウザとサーバーの間に TCP 接続に基づく双方向チャネルが提供されます。 Web 開発者は、WebSocket を使用してリアルタイム Web アプリケーションを簡単に構築できるようになり、開発者は新たな魔法の武器を手に入れることができました。この記事では、まず HTML5 WebSocket の基本概念とこの仕様が解決しようとしている問題を紹介し、次に WebSocket の基本原理とプログラミング インターフェイスを紹介します。次に、簡単なケースを使用して WebSocket アプリケーションの実装方法を示し、WebSocket が強力な機能と使いやすいプログラミングの完全な統合をどのように実現できるかを示します。最後に、主流ブラウザにおける WebSocket サポートの現状、制限、将来の見通しについて紹介します。

リアルタイム Web アプリケーションのジレンマ

Web アプリケーションの情報対話プロセスは、通常、クライアントがブラウザーを介してリクエストを送信し、サーバーがリクエストを受信して​​レビューし、処理して結果をクライアントに返し、そしてその後、クライアントのブラウザが情報を送信します。このメカニズムは、情報の変更が特に頻繁ではないアプリケーションではまだ問題ありませんが、オンライン ゲーム、オンライン証券、機器の監視、オンライン ニュース放送など、リアルタイム性の要件が高いアプリケーションでは問題ありません。 、および RSS サブスクリプション プッシュを待つと、クライアント ブラウザーがこの情報をレンダリングする準備が整うまでに、サーバー側の情報が古くなっている可能性があります。したがって、クライアント側とサーバー側の情報の同期を維持することは、リアルタイム Web アプリケーションの重要な要素であり、Web 開発者にとっては難しい問題でもあります。 WebSocket 仕様が発表される前、これらのリアルタイム Web アプリケーションを実装したい開発者は、いくつかの妥協策を採用する必要がありました。その中で最も一般的に使用されていたのはポーリングと Comet テクノロジーであり、Comet テクノロジーは実際にはポーリング テクノロジーを改良したものである可能性があります。 1 つはロング ポーリング メカニズム、もう 1 つはストリーミング テクノロジと呼ばれる実装方法です。これらのテクノロジーを簡単に紹介します。

ポーリング:

これは、リアルタイム Web アプリケーションを実装するための最も初期のソリューションです。クライアントは一定の間隔でサーバーにリクエストを送信し、頻繁なリクエストによってクライアントとサーバー間の同期を維持します。この同期スキームの最大の問題は、クライアントが一定の頻度でサーバーへのリクエストを開始すると、サーバー側のデータが更新されない可能性があり、不必要なネットワーク送信が大量に発生するため、非常に非効率であることです。リアルタイムプラン。

ロングポーリング:

ロングポーリングは、無効なネットワーク送信を減らすことを目的とした、スケジュールされたポーリングの改良および強化です。サーバー側でデータの更新がない場合、データまたはステータスが変更されるか、時間が経過するまで、接続は一定期間維持されます。このメカニズムにより、クライアントとサーバー間の無効な対話が減少します。もちろん、サーバー上のデータが非常に頻繁に変更される場合、このメカニズムではスケジュールされたポーリングと比較してパフォーマンスが大幅に向上することはありません。

ストリーミング:

ストリーミング テクノロジ ソリューションは通常、クライアント ページの非表示ウィンドウを使用して、サーバーに長い接続リクエストを発行します。このリクエストを受信した後、サーバーは応答し、クライアントとサーバー間の接続が期限切れにならないように接続ステータスを継続的に更新します。このメカニズムを通じて、サーバー側の情報をクライアントに継続的にプッシュできます。このメカニズムには、ユーザー エクスペリエンスに関していくつかの問題があります。ユーザー エクスペリエンスを向上させるには、ブラウザごとに異なるソリューションを設計する必要があります。同時に、このメカニズムは、同時実行性が比較的大きい場合には、サーバー側のリソースにとって優れたテストとなります。

これらのソリューションを組み合わせると、現在使用しているいわゆるリアルタイム テクノロジは、クライアントとサーバーが対話するたびにリアルタイム効果をシミュレートするために Ajax を使用しているだけであることがわかります。は毎回 HTTP リクエストとレスポンスのプロセスであり、各 HTTP リクエストとレスポンスには完全な HTTP ヘッダー情報が含まれるため、毎回送信されるデータ量が増加し、これらのソリューションにおけるクライアントとサーバーのプログラミングは比較的複雑です。実際のアプリケーションでは、より現実的なリアルタイム効果をシミュレートするために、多くの場合、開発者はクライアントとサーバー間の双方向通信をシミュレートするために 2 つの HTTP 接続を構築する必要があり、1 つの接続はクライアントからサーバーへの通信の処理に使用されます。データ送信では、サーバーからクライアントへのデータ送信を処理するために接続が使用されます。これにより、必然的にプログラミングの実装が複雑になり、サーバーの負荷が増大し、アプリケーション システムのスケーラビリティが制限されます。

WebSocket の助け

HTML5 WebSocket は、ポーリングと Comet テクノロジーを置き換えるように設計されているため、クライアント ブラウザーは、C/S アーキテクチャ下のデスクトップ システムと同様のリアルタイム通信機能を備えています。 ブラウザは、JavaScript を介して WebSocket 接続を確立するリクエストをサーバーに送信します。接続が確立されると、クライアントとサーバーは TCP 接続を通じて直接データを交換できます。 WebSocket 接続は本質的に TCP 接続であるため、ポーリングや Comet テクノロジと比較して、データ送信の安定性とデータ送信量の点でパフォーマンスに大きな利点があります。 Websocket.org Web サイトは、従来のポーリング方式と WebSocket 呼び出し方式の詳細なテストと比較を実施しました。以下は、そのテスト結果からの引用です。ポーリングと WebSocket 実装間のネットワーク負荷の比較

この図から、トラフィックと負荷が増加すると、WebSocket ソリューションが従来の Ajax ポーリング ソリューションよりも大幅に優れていることがわかります。これが、WebSocket が将来のリアルタイム Web アプリケーションに最適なソリューションであると当社が信じている理由です。

WebSocket 仕様

WebSocket プロトコルは、本質的には TCP ベースのプロトコルです。 WebSocket 接続を確立するには、クライアントのブラウザーが最初にサーバーへの HTTP リクエストを開始する必要があります。このリクエストは通常​​の HTTP リクエストとは異なり、追加のヘッダー情報

「Upgrade: WebSocket」 がそれを示します。これは、プロトコルのアップグレードを申請するための HTTP リクエストの場合、サーバーはこれらの追加のヘッダー情報を解析し、応答情報を生成してクライアントに返します。クライアントとサーバー間の WebSocket 接続が確立され、双方が自由に接続できます。この接続チャネルを通じて情報を転送します。この接続は、クライアントまたはサーバーが接続をアクティブに閉じるまで存在し続けます。

WebSocket 仕様を詳しく紹介しましょう。この仕様はまだドラフト段階にあり、バージョンはすぐに変更されるため、WebSocket プロトコルを説明するために

draft-hixie-thewebsocketprotocol-76 バージョンを選択します。このバージョンは現在、Chrome、FireFox、Opera などの一部の主流ブラウザで十分にサポートされているため、新しいバージョンを参照している場合は、内容が若干異なる場合があります。

WebSocket リクエストとレスポンスの典型的な例は次のとおりです:

リスト 1. WebSocket ハンドシェイク プロトコル

<strong>客户端到服务端:</strong> GET /demo HTTP/1.1 Host: example.com Connection: Upgrade Sec-WebSocket-Key2: 12998 5 Y3 1 .P00 Upgrade: WebSocket Sec-WebSocket-Key1: 4@1 46546xW%0l 1 5 Origin: http://example.com [8-byte security key] <strong>服务端到客户端:</strong>HTTP/1.1 101 WebSocket Protocol Handshake Upgrade: WebSocket Connection: Upgrade WebSocket-Origin: http://example.com WebSocket-Location: ws://example.com/demo [16-byte hash response]

これらのリクエストは通常​​の HTTP リクエストに非常に似ていますが、その一部は WebSocket プロトコルに密接に関連しています。これらのリクエストとレスポンスの情報について簡単に説明します。「Upgrade:WebSocket」は、このリクエストの目的が、クライアントとサーバー間の通信プロトコルを HTTP プロトコルから WebSocket プロトコルにアップグレードすることであることを意味します。 。クライアントからサーバーに要求される情報には、「Sec-WebSocket-Key1」、「Sec-WebSocket-Key2」、「[8バイトのセキュリティキー]」などのヘッダ情報が含まれます。これは、クライアントのブラウザがサーバーに提供する必要があるハンドシェイク情報です。サーバーはこれらのヘッダー情報を解析し、ハンドシェイク プロセス中にこの情報に基づいて 16 ビットのセキュリティ キーを生成し、それをクライアントに返してサーバーが持っていることを示します。取得 クライアントの要求を受け入れ、WebSocket 接続の作成に同意します。接続が確立されると、クライアントとサーバーはこのチャネルを通じて双方向にデータを送信できます。

実際の開発プロセスでは、WebSocket インターフェースを使用して Web アプリケーションを構築するには、まず WebSocket 仕様を実装するサーバーを構築する必要があります。サーバー側の実装はプラットフォームと開発言語のみに制限されません。現在、次のような比較的成熟した WebSocket サーバー側の実装があります。

Kaazing WebSocket ゲートウェイ ? Python で実装された WebSocket サーバー
  • Netty ? WebSocket サポートを含む、Java で実装されたネットワーク フレームワーク
  • node.js ? サーバー側 JavaScript フレームワークが WebSocket のサポートを提供します
  • 上記の WebSocket サーバー実装がビジネス ニーズを満たせない場合、開発者は以下に従ってサーバーを独自に実装できます。 WebSocketの仕様。 「WebSocket 実践戦闘」セクションでは、Microsoft .NET プラットフォーム上で C# 言語を使用して単純な WebSocket サーバーを構築し、その後、単純なリアルタイム チャット システムを構築します。
  • WebSocket JavaScript インターフェイス

    前のセクションでは WebSocket 仕様を紹介し、主に WebSocket ハンドシェイク プロトコルを紹介しました。ハンドシェイク プロトコルは、通常、WebSocket サーバー側の実装を構築し、ブラウザーの WebSocket サポートを提供するときに考慮する必要があります。Web 開発者向けの WebSocket JavaScript クライアント インターフェイスは、次のとおりです。 WebSocket JavaScript インターフェイスの定義は次のとおりです。 WebSocket JavaScript 定義

    うわー

    其中 URL 属性代表 WebSocket 服务器的网络地址,协议通常是”ws”,send 方法就是发送数据到服务器端,close 方法就是关闭连接。除了这些方法,还有一些很重要的事件:onopen,onmessage,onerror 以及 onclose。我们借用 Nettuts 网站上的一张图来形象的展示一下 WebSocket 接口:

    图 2. WebSocket JavaScript 接口

    下面是一段简单的 JavaScript 代码展示了怎样建立 WebSocket 连接和获取数据:

    清单 3. 建立 WebSocket 连接的实例 JavaScript 代码

     var  wsServer = 'ws://localhost:8888/Demo';  var  websocket = new WebSocket(wsServer);  websocket.onopen = function (evt) { onOpen(evt) };  websocket.onclose = function (evt) { onClose(evt) };  websocket.onmessage = function (evt) { onMessage(evt) };  websocket.onerror = function (evt) { onError(evt) };  function onOpen(evt) {  console.log("Connected to WebSocket server.");  }  function onClose(evt) {  console.log("Disconnected");  }  function onMessage(evt) {  console.log('Retrieved data from server: ' + evt.data);  }  function onError(evt) {  console.log('Error occured: ' + evt.data);  }

     

     

    浏览器支持

    下面是主流浏览器对 HTML5 WebSocket 的支持情况:

    浏览器 支持情况
    Chrome Supported in version 4+
    Firefox Supported in version 4+
    Internet Explorer Supported in version 10+
    Opera Supported in version 10+
    Safari Supported in version 5+

     

     

    WebSocket 实战

    这一节里我们用一个案例来演示怎么使用 WebSocket 构建一个实时的 Web 应用。这是一个简单的实时多人聊天系统,包括客户端和服务端的实现。客户端通过浏览器向聊天服务器发起请求,服务器端解析客户端发出的握手请求并产生应答信息返回给客户端,从而在客户端和服务器之间建立连接通道。服务器支持广播功能,每个聊天用户发送的信息会实时的发送给所有的用户,当用户退出聊天室时,服务器端需要清理相应用户的连接信息,避免资源的泄漏。以下我们分别从服务器端和客户端来演示这个 Web 聊天系统的实现,在实现方式上我们采用了 C# 语言来实现 WebSocket 服务器,而客户端是一个运行在浏览器里的 HTML 文件。

    WebSocket 服务器端实现

    这个聊天服务器的实现和基于套接字的网络应用程序非常类似,首先是服务器端要启动一个套接字监听来自客户端的连接请求,关键的区别在于 WebSocket 服务器需要解析客户端的 WebSocket 握手信息,并根据 WebSocket 规范的要求产生相应的应答信息。一旦 WebSocket 连接通道建立以后,客户端和服务器端的交互就和普通的套接字网络应用程序是一样的了。所以在下面的关于 WebSocket 服务器端实现的描述中,我们主要阐述 WebSocket 服务器怎样处理 WebSocket 握手信息,至于 WebSocket 监听端口的建立,套接字信息流的读取和写入,都是一些常用的套接字编程的方式,我们就不多做解释了,您可以自行参阅本文的附件源代码文件。

    在描述 WebSocket 规范时提到,一个典型的 WebSocket Upgrade 信息如下所示:

    GET /demo HTTP/1.1 Host: example.com Connection: Upgrade Sec-WebSocket-Key2: 12998 5 Y3 1 .P00 Upgrade: WebSocket Sec-WebSocket-Key1: 4@1 46546xW%0l 1 5 Origin: http://example.com [8-byte security key]

    其中 Sec-WebSocket-Key1,Sec-WebSocket-Key2 和 [8-byte security key] 这几个头信息是 WebSocket 服务器用来生成应答信息的来源,依据draft-hixie-thewebsocketprotocol-76 草案的定义,WebSocket 服务器基于以下的算法来产生正确的应答信息:

    1. 逐个字符读取 Sec-WebSocket-Key1 头信息中的值,将数值型字符连接到一起放到一个临时字符串里,同时统计所有空格的数量;
    2. 将在第 1 步里生成的数字字符串转换成一个整型数字,然后除以第 1 步里统计出来的空格数量,将得到的浮点数转换成整数型;
    3. 将第 2 步里生成的整型值转换为符合网络传输的网络字节数组;
    4. 对 Sec-WebSocket-Key2 头信息同样进行第 1 到第 3 步的操作,得到另外一个网络字节数组;
    5. 将 [8-byte security key] 和在第 3,第 4 步里生成的网络字节数组合并成一个 16 字节的数组;
    6. 对第 5 步生成的字节数组使用 MD5 算法生成一个哈希值,这个哈希值就作为安全密钥返回给客户端,以表明服务器端获取了客户端的请求,同意创建 WebSocket 连接

    至此,客户端和服务器的 WebSocket 握手就完成了,WebSocket 通道也建立起来了。下面首先介绍一下服务器端实现是如何根据用户传递的握手信息来生成网络字节数组的。.NET 平台提供了很方便的对字符串,数值以及数组操作的函数,所以生成字节数组的方法还是非常简单明了的,代码如下:

    清单 4. 生成网络字节数组的代码

        private byte[]   BuildServerPartialKey(string clientKey)  {       string partialServerKey = "";      byte[] currentKey;      int spacesNum = 0;      char[] keyChars = clientKey.ToCharArray();      foreach (char currentChar in keyChars)      {          if (char.IsDigit(currentChar)) partialServerKey += currentChar;         if (char.IsWhiteSpace(currentChar)) spacesNum++;      }      try      {               currentKey = BitConverter.GetBytes((int)(Int64.Parse(partialServerKey)  / spacesNum));         if (BitConverter.IsLittleEndian) Array.Reverse(currentKey);      }      catch      {         if (currentKey!= null) Array.Clear(currentKey, 0, currentKey.Length);      }      return currentKey;   }

    得到网络字节数组以后,服务器端生成 16 位安全密钥的方法如下所示:

    清单 5. 生成 16 位安全密钥的代码

     private byte[] BuildCompleteServerKey(byte[] serverKey1, byte[] serverKey2,  byte[] last8Bytes)  {      byte[] concatenatedKeys = new byte[16];     Array.Copy(serverKey1, 0, concatenatedKeys, 0, 4);     Array.Copy(serverKey2, 0, concatenatedKeys, 4, 4);     Array.Copy(last8Bytes, 0, concatenatedKeys, 8, 8);     System.Security.Cryptography.MD5 MD5Service =  System.Security.Cryptography.MD5.Create();    return MD5Service.ComputeHash(concatenatedKeys);  }

    整个实现是非常简单明了的,就是将生成的网络字节数组和客户端提交的头信息里的 [8-byte security key] 合并成一个 16 位字节数组并用 MD5 算法加密,然后将生成的安全密钥作为应答信息返回给客户端,双方的 WebSocekt 连接通道就建立起来了。实现了 WebSocket 握手信息的处理逻辑,一个具有基本功能的 WebSocket 服务器就完成了。整个 WebSocket 服务器由两个核心类构成,一个是 WebSocketServer,另外一个是 SocketConnection,出于篇幅的考虑,我们不介绍每个类的属性和方法了,文章的附件会给出详细的源代码,有兴趣的读者可以参考。

    服务器刚启动时的画面如下:

    图 3. WebSocket 服务器刚启动的画面

    客户端可以依据这个信息填写聊天服务器的连接地址,当有客户端连接到聊天服务器上时,服务器会打印出客户端和服务器的握手信息,每个客户的聊天信息也会显示在服务器的界面上,运行中的聊天服务器的界面如下:

    图 4. 有客户端连接到 WebSocket 服务器的

    以上我们简单描述了实现一个 WebSocket 服务器的最基本的要素,下一节我们会描述客户端的实现。

    客户端实现

    客户端的实现相对于服务器端的实现来说要简单得多了,我们只需要发挥想象去设计 HTML 用户界面,然后呼叫 WebSocket JavaScript 接口来和 WebSocket 服务器端来交互就可以了。当然别忘了使用一个支持 HTML5 和 WebSocket 的浏览器,在笔者写这篇文章的时候使用的浏览器是 Firefox。客户端的页面结构是非常简洁的,初始运行界面如下:

    图 5. 聊天室客户端初始页面

    当页面初次加载的时候,首先会检测当前的浏览器是否支持 WebSocket 并给出相应的提示信息。用户按下连接按钮时,页面会初始化一个到聊天服务器的 WebSocekt 连接,初始化成功以后,页面会加载对应的 WebSocket 事件处理函数,客户端 JavaScript 代码如下所示:

    清单 6. 初始化客户端 WebSocket 对象的代码

     function ToggleConnectionClicked() {          if (SocketCreated && (ws.readyState == 0 || ws.readyState == 1)) {                  ws.close();            } else {                Log("准备连接到聊天服务器 ...");                try {                 ws =                  new WebSocket("ws://" + document.getElementById("Connection").value);                  SocketCreated = true;                } catch (ex) {                  Log(ex, "ERROR");                  return;                }                document.getElementById("ToggleConnection").innerHTML = "断开";                ws.onopen = WSonOpen;                ws.onmessage = WSonMessage;                ws.onclose = WSonClose;                ws.onerror = WSonError;            }        };        function WSonOpen() {            Log("连接已经建立。", "OK");            $("#SendDataContainer").show("slow");        };        function WSonMessage(event) {            Log(event.data);                    };        function WSonClose() {            Log("连接关闭。", "ERROR");            document.getElementById("ToggleConnection").innerHTML = "连接";            $("#SendDataContainer").hide("slow");        };        function WSonError() {            Log("WebSocket错误。", "ERROR");        };

    当用户按下发送按钮,客户端会调用WebSocket对象向服务器发送信息,并且这个消息会广播给所有的用户,实现代码如下所示:

    function SendDataClicked() {            if (document.getElementById("DataToSend").value != "") {                ws.send(document.getElementById("txtName").value + "说 :\"" + document.getElementById("DataToSend").value + "\"");                document.getElementById("DataToSend").value = "";            }        };

    如果有多个用户登录到聊天服务器,客户端页面的运行效果如下所示:

    图 6. 聊天客户端运行页面

    至此我们已经完成了一个完整的 WebSocket 客户端实现,用户可以体验一下这个聊天室的简单和快捷,完全不用考虑页面的刷新和繁琐的 Ajax 调用,享受桌面程序的用户体验。WebSocket 的强大和易用可见一斑,您完全可以在这个基础上加入更多的功能,设计更加漂亮的用户界面,切身体验 WebSocket 的震撼力。完整的客户端代码请参阅附件提供的源代码。

     

     

    WebSocket 的局限性

    WebSocket 的优点已经列举得很多了,但是作为一个正在演变中的 Web 规范,我们也要看到目前用 Websocket 构建应用程序的一些风险。首先,WebSocket 规范目前还处于草案阶段,也就是它的规范和 API 还是有变动的可能,另外的一个风险就是微软的 IE 作为占市场份额最大的浏览器,和其他的主流浏览器相比,对 HTML5 的支持是比较差的,这是我们在构建企业级的 Web 应用的时候必须要考虑的一个问题。

     

     

    总结

    本文介绍了 HTML5 WebSocket 的横空出世以及它尝试解决的的问题,然后介绍了 WebSocket 规范和 WebSocket 接口,以及和传统的实时技术相比在性能上的优势,并且演示了怎样使用 WebSocket 构建一个实时的 Web 应用,最后我们介绍了当前的主流浏览器对 HTML5 的支持情况和 WebSocket 的局限性。不过,我们应该看到,尽管 HTML5 WebSocket 目前还有一些局限性,但是已经是大势所趋,微软也明确表达了未来对 HTML5 的支持,而且这些支持我们可以在 Windows 8 和 IE10 里看到,我们也在各种移动设备,平板电脑上看到了 HTML5 和 WebSocket 的身影。WebSocket 将会成为未来开发实时 Web 应用的生力军应该是毫无悬念的了,作为 Web 开发人员,关注 HTML5,关注 WebSocket 也应该提上日程了,否则我们在新一轮的软件革新的浪潮中只能做壁上观了。

     

    转自 http://www.ibm.com/developerworks/cn/web/1112_huangxa_websocket/

     

    下载

    描述 名字 大小 示例代码
    new-source.zip 94KB
    声明:
    この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。