Websockets-quick-guide
WebSocket-概要
文字通り、ハンドシェイクは、挨拶、お祝い、同意、または別れを象徴するために、2人の個人による右手の握りと握手として定義できます。 コンピューターサイエンスでは、ハンドシェイクはサーバーとクライアントを確実に同期させるプロセスです。 ハンドシェイクは、Web Socketプロトコルの基本概念です。
次の図は、さまざまなクライアントとのサーバーハンドシェイクを示しています-
Webソケット-定義
Webソケットは、サーバーとクライアント間の双方向通信として定義されます。これは、両者が同時に通信し、データを交換することを意味します。
Web Socketsの重要なポイントは、*真の同時実行性*および*パフォーマンスの最適化*であり、より応答性が高くリッチなWebアプリケーションをもたらします。
Web Socket Protocolの説明
このプロトコルは、一から全二重通信を定義します。 Webソケットは、デスクトップの豊富な機能をWebブラウザーにもたらすために一歩前進します。 これは、クライアント/サーバーWebテクノロジーで長い間待ち望まれていた進化を表しています。
Webソケットの主な機能は次のとおりです-
- Webソケットプロトコルは標準化されています。つまり、このプロトコルを使用すると、Webサーバーとクライアント間のリアルタイム通信が可能になります。
- Webソケットは、クライアントとサーバー間のリアルタイム通信のためのクロスプラットフォーム標準に変換されています。
- この標準は、新しい種類のアプリケーションを可能にします。 リアルタイムWebアプリケーションのビジネスは、このテクノロジーの助けを借りてスピードアップできます。
- Web Socketの最大の利点は、単一のTCP接続で双方向通信(全二重)を提供することです。
URL
HTTPには、httpやhttpsなどの独自のスキーマセットがあります。 Webソケットプロトコルには、URLパターンで定義された同様のスキーマもあります。
次の画像は、トークン内のWebソケットURLを示しています。
ブラウザのサポート
Web Socketプロトコルの最新の仕様は、 RFC 6455 –提案された標準として定義されています。
*RFC 6455* は、Internet Explorer、Mozilla Firefox、Google Chrome、Safari、Operaなどのさまざまなブラウザーでサポートされています。
WebSocket-二重通信
Webソケットの必要性に飛び込む前に、サーバーとクライアント間の*デュプレックス通信*に使用される既存のテクニックを確認する必要があります。 彼らは次のとおりです-
- 投票
- ロングポーリング
- ストリーミング
- ポストバックとAJAX
- HTML5
投票
ポーリングは、伝送に存在するデータに関係なく定期的な要求を実行する方法として定義できます。 定期的なリクエストは同期的に送信されます。 クライアントは、サーバーに対して指定された時間間隔で定期的な要求を行います。 サーバーの応答には、使用可能なデータまたは警告メッセージが含まれています。
ロングポーリング
名前が示すように、長いポーリングにはポーリングのような同様の手法が含まれます。 クライアントとサーバーは、一部のデータが取得されるかタイムアウトが発生するまで、接続をアクティブに保ちます。 何らかの理由で接続が失われた場合、クライアントは最初からやり直して順次要求を実行できます。
長いポーリングは、ポーリングプロセスよりもパフォーマンスが向上するだけですが、要求が絶えず続くとプロセスが遅くなる場合があります。
ストリーミング
これは、リアルタイムのデータ伝送に最適なオプションと見なされています。 サーバーは、必要なデータがフェッチされるまで、クライアントが接続を開いたままアクティブにします。 この場合、接続は無期限に開いていると言われます。 ストリーミングにはHTTPヘッダーが含まれているため、ファイルサイズが大きくなり、遅延が大きくなります。 これは大きな欠点と考えられます。
AJAX
AJAXは、Javascriptの XmlHttpRequest オブジェクトに基づいています。 これは、非同期JavascriptおよびXMLの短縮形です。 XmlHttpRequest オブジェクトを使用すると、Webページ全体をリロードせずにJavascriptを実行できます。 AJAXはWebページの一部のみを送受信します。
*XmlHttpRequest* オブジェクトを使用したAJAX呼び出しのコードスニペットは次のとおりです-
var xhttp;
if (window.XMLHttpRequest) {
xhttp = new XMLHttpRequest();
} else {
//code for IE6, IE5
xhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
- Webソケット*と比較した AJAX の主な欠点は次のとおりです-
- HTTPヘッダーを送信するため、合計サイズが大きくなります。
- 通信は半二重です。
- Webサーバーはより多くのリソースを消費します。
HTML5
HTML5は、Webアプリケーションを開発および設計するための堅牢なフレームワークです。 主な柱には、マークアップ、CSS3 *、 *Javascript APIが含まれます。
次の図は、HTML5コンポーネントを示しています-
以下に示すコードスニペットは、HTML5の宣言とそのdoctypeを説明しています。
<!DOCTYPE html>
Webソケットが必要な理由
インターネットは、相互にリンクして概念的な情報のウェブを形成するハイパーテキストマークアップ言語(HTML)ページの集まりであると考えられていました。 時間が経つにつれて、静的リソースの数が増え、画像などのより豊富なアイテムが増え、Webファブリックの一部になり始めました。
動的サーバーページ-クエリに基づいてコンテンツが生成されたページを許可する高度なサーバーテクノロジー。
すぐに、より動的なWebページを持つという要件により、Dynamic Hypertext Mark-up Language(DHTML)が利用可能になります。 JavaScriptのおかげです。 その後数年間、ページのリロードを回避する試みで*フレーム間通信*が発生し、その後にフレーム内で* HTTPポーリング*が行われました。
ただし、これらのソリューションはいずれも、サーバーとクライアント間のリアルタイムの双方向通信に真に標準化されたクロスブラウザーソリューションを提供していません。
これにより、Web Sockets Protocolが必要になりました。 全二重通信が発生し、すべてのWebブラウザーにデスクトップの豊富な機能がもたらされました。
WebSocket-機能
Web Socketは、Web通信の歴史における主要なアップグレードです。 存在する前は、Webクライアントとサーバー間のすべての通信はHTTPのみに依存していました。
Web Socketは、永続的な全二重の接続の動的フローを支援します。 全二重とは、かなりの高速での両端からの通信を指します。
既存のプロトコルのすべての欠点を克服する効率のため、ゲームチェンジャーと呼ばれています。
開発者およびアーキテクト向けのWebソケット
開発者および設計者にとってのWeb Socketの重要性-
- Web Socketは独立したTCPベースのプロトコルですが、従来は純粋なTCP接続の上でのみ実行される他のプロトコルをサポートするように設計されています。
- Web Socketは、他のプロトコルを実行できるトランスポート層です。 Web Socket APIは、サブプロトコルを定義する機能をサポートしています。サブプロトコルは、特定のプロトコルを解釈できるプロトコルライブラリです。
- そのようなプロトコルの例には、XMPP、STOMP、およびAMQPが含まれます。 開発者は、HTTPリクエスト/レスポンスパラダイムの観点から考える必要がなくなりました。
- ブラウザー側の唯一の要件は、Web Socketハンドシェイクを解釈し、Web Socket接続を確立および維持できるJavaScriptライブラリを実行することです。
- サーバー側では、業界標準では、TCP上で実行され、Web Socket Gatewayを活用する既存のプロトコルライブラリを使用します。
次の図は、Webソケットの機能について説明しています-
Webソケット接続はHTTP経由で開始されます。 HTTPサーバーは通常、Webソケットハンドシェイクをアップグレード要求として解釈します。
Web Socketsは、既存のHTTP環境への補完的なアドオンであり、Web機能を追加するために必要なインフラストラクチャを提供できます。 クライアントとサーバー間の双方向のデータフローを可能にする、より高度な全二重プロトコルに依存しています。
Webソケットの機能
Webソケットは、両者がデータの送信を開始できるように、Webサーバーとクライアント間の接続を提供します。
Web Socketの接続を確立するための手順は次のとおりです-
- クライアントは、Webソケットハンドシェイクと呼ばれるプロセスを介して接続を確立します。
- このプロセスは、クライアントが通常のHTTP要求をサーバーに送信することから始まります。
- Upgradeヘッダーが要求されます。 このリクエストでは、リクエストがWeb Socket接続用であることをサーバーに通知します。
- WebソケットURLは ws スキームを使用します。 また、HTTPと同等のセキュアWebソケット接続にも使用されます。
初期リクエストヘッダーの簡単な例は次のとおりです-
GET ws://websocket.example.com/HTTP/1.1
Origin: http://example.com
Connection: Upgrade
Host: websocket.example.com
Upgrade: websocket
WebSocket-実装
Web Socketsは、Webだけでなくモバイル業界でも重要な役割を担っています。 Webソケットの重要性を以下に示します。
- 名前が示すように、WebソケットはWebに関連しています。 Webは、一部のブラウザー向けの一連の手法で構成されています。これは、デスクトップコンピューター、ラップトップ、タブレット、スマートフォンなど、膨大な数のデバイス向けの広範な通信プラットフォームです。
- Web Socketsを利用するHTML5アプリは、HTML5対応のWebブラウザーで動作します。
- Webソケットは、主流のオペレーティングシステムでサポートされています。 モバイル業界の主要なプレーヤーはすべて、独自のネイティブアプリでWeb Socket APIを提供しています。
- Webソケットは、全二重通信と呼ばれます。 Web Socketsのアプローチは、チャットルームなど、クライアントとサーバーからの更新が同時に共有される特定のカテゴリのWebアプリケーションに適しています。
HTML5仕様の一部であるWeb Socketsは、Webページとリモートホスト間の全二重通信を可能にします。 プロトコルは、キーポイントとみなすことができる次の利点を達成するように設計されています-
- (2つではなく)1つの接続を介した全二重通信を使用して、不要なネットワークトラフィックと待機時間を削減します。
- プロキシとファイアウォールを介したストリーミング、アップストリームとダウンストリームの通信を同時にサポートします。
WebSockets-イベントとアクション
クライアント間の通信のために、クライアントからサーバーへの接続を初期化する必要があります。 接続を初期化するには、リモートサーバーまたはローカルサーバーでURLを使用してJavaScriptオブジェクトを作成する必要があります。
var socket = new WebSocket(“ ws://echo.websocket.org ”);
上記のURLは、テストと実験に使用できるパブリックアドレスです。 websocket.orgサーバーは常に稼働しており、メッセージを受信してクライアントに送り返します。
これは、アプリケーションが正しく機能することを保証するための最も重要なステップです。
Webソケット-イベント
4つのメインWebソケットAPI *イベント*があります-
- Open
- メッセージ
- 閉じる
- エラー
各イベントは、それぞれ onopen、onmessage 、 onclose 、 onerror 関数などの関数を実装することで処理されます。 addEventListenerメソッドの助けを借りて実装することもできます。
イベントと機能の簡単な概要は次のとおりです-
Open
クライアントとサーバーの間で接続が確立されると、Web Socketインスタンスからopenイベントが発生します。 これは、クライアントとサーバー間の最初のハンドシェイクとして呼び出されます。 接続が確立されると発生するイベントは、 onopen と呼ばれます。
メッセージ
通常、メッセージイベントは、サーバーがデータを送信するときに発生します。 サーバーからクライアントに送信されるメッセージには、プレーンテキストメッセージ、バイナリデータ、または画像を含めることができます。 データが送信されるたびに、 onmessage 関数が起動されます。
閉じる
Closeイベントは、サーバーとクライアント間の通信の終了を示します。 接続を閉じるには、 onclose イベントを使用します。 onclose イベントを使用して通信の終了をマークした後、サーバーとクライアントの間でメッセージをさらに転送することはできません。 接続が不十分なために、イベントを閉じることもできます。
エラー
通信中に発生する何らかの誤りのエラーマーク。 onerror イベントの助けを借りてマークされます。 Onerror の後には常に接続の終了が続きます。 各イベントの詳細な説明については、以降の章で説明します。
Webソケット-アクション
イベントは通常、何かが発生したときにトリガーされます。 一方、ユーザーが何かをしたいときにアクションが取られます。 アクションは、ユーザーによる関数を使用した明示的な呼び出しによって行われます。
Web Socketプロトコルは、2つの主要なアクションをサポートしています-
- send()
- 閉じる()
送信()
通常、このアクションは、テキストファイル、バイナリデータ、または画像を含むメッセージの送信を含むサーバーとの通信に適しています。
send()アクションの助けを借りて送信されるチャットメッセージは次のとおりです-
//get text view and button for submitting the message
var textsend = document.getElementById(“text-view”);
var submitMsg = document.getElementById(“tsend-button”);
//Handling the click event
submitMsg.onclick = function ( ) {
//Send the data
socket.send( textsend.value);
}
注-メッセージの送信は、接続が開いている場合にのみ可能です。
閉じる()
この方法は、さよならハンドシェイクの略です。 接続を完全に終了し、接続が再確立されるまでデータを転送できません。
var textsend = document.getElementById(“text-view”);
var buttonStop = document.getElementById(“stop-button”);
//Handling the click event
buttonStop.onclick = function ( ) {
//Close the connection if open
if (socket.readyState === WebSocket.OPEN){
socket.close( );
}
}
次のコードスニペットの助けを借りて意図的に接続を閉じることも可能です-
socket.close(1000,”Deliberate Connection”);
WebSockets-接続を開く
クライアントとサーバー間で接続が確立されると、Web Socketインスタンスからopenイベントが発生します。 これは、クライアントとサーバー間の最初のハンドシェイクとして呼び出されます。
接続が確立されると発生するイベントは、 onopen と呼ばれます。 Web Socket接続の作成は本当に簡単です。 必要なのは、* WebSocketコンストラクター*を呼び出して、サーバーのURLを渡すだけです。
次のコードは、Web Socket接続を作成するために使用されます-
//Create a new WebSocket.
var socket = new WebSocket('ws://echo.websocket.org');
接続が確立されると、Web Socketインスタンスでopenイベントが発生します。
*onopen* は、クライアントとサーバー間の最初のハンドシェイクを指します。これは最初の取引につながり、Webアプリケーションはデータを送信する準備ができています。
次のコードスニペットは、Web Socketプロトコルの接続を開くことを説明しています-
socket.onopen = function(event) {
console.log(“Connection established”);
//Display user friendly messages for the successful establishment of connection
var.label = document.getElementById(“status”);
label.innerHTML = ”Connection established”;
}
Webソケット接続の確立を待っているユーザーに適切なフィードバックを提供することをお勧めします。 ただし、Web Socket接続は比較的高速であることに常に注意してください。
確立されたWebソケット接続のデモは、次のURLに記載されています-https://www.websocket.org/echol
接続の確立とユーザーへの応答のスナップショットを以下に示します-
オープン状態を確立すると、接続が終了するまで全二重通信とメッセージの転送が可能になります。
例
クライアントHTML5ファイルを作成します。
<!DOCTYPE html>
<html>
<meta charset = "utf-8"/>
<title>WebSocket Test</title>
<script language = "javascript" type = "text/javascript">
var wsUri = "ws://echo.websocket.org/";
var output;
function init() {
output = document.getElementById("output");
testWebSocket();
}
function testWebSocket() {
websocket = new WebSocket(wsUri);
websocket.onopen = function(evt) {
onOpen(evt)
};
}
function onOpen(evt) {
writeToScreen("CONNECTED");
}
window.addEventListener("load", init, false);
</script>
<h2>WebSocket Test</h2>
<div id = "output"></div>
</html>
出力は次のようになります-
上記のHTML5およびJavaScriptファイルは、Web Socketの2つのイベントの実装を示しています。
- JavaScriptオブジェクトの作成と接続の初期化に役立つ onLoad 。
- onOpen はサーバーとの接続を確立し、ステータスも送信します。
WebSockets-エラー処理
クライアントとサーバーの間で接続が確立されると、Web Socketインスタンスから open イベントが発生します。 通信中に発生する間違いに対してエラーが生成されます。 onerror イベントの助けを借りてマークされます。 Onerror の後には常に接続の終了が続きます。
*onerror* イベントは、通信間に何らかの問題が発生したときに発生します。 イベント *onerror* の後に接続終了が続きます。これは *close* イベントです。
予期しないエラーについて常にユーザーに通知し、それらを再接続することをお勧めします。
socket.onclose = function(event) {
console.log("Error occurred.");
//Inform the user about the error.
var label = document.getElementById("status-label");
label.innerHTML = "Error: " + event;
}
エラー処理に関しては、内部パラメーターと外部パラメーターの両方を考慮する必要があります。
- 内部パラメーターには、コードのバグ、または予期しないユーザーの動作のために生成される可能性のあるエラーが含まれます。
- 外部エラーはアプリケーションとは関係ありません。むしろ、それらは制御できないパラメーターに関連しています。 最も重要なものは、ネットワーク接続です。
- 双方向の双方向Webアプリケーションには、アクティブなインターネット接続が必要です。
ネットワークの可用性の確認
タスクの途中で突然ネットワーク接続が応答しなくなったときに、ユーザーがWebアプリを楽しんでいると想像してください。 最新のネイティブデスクトップおよびモバイルアプリケーションでは、ネットワークの可用性を確認することが一般的なタスクです。
最も一般的な方法は、稼働しているはずのWebサイト(http://www.google.comなど)にHTTPリクエストを送信するだけです。 要求が成功すると、デスクトップまたはモバイルデバイスはアクティブな接続があることを認識します。 同様に、HTMLには、ネットワークの可用性を判別するための XMLHttpRequest があります。
ただし、HTML5ではさらに簡単になり、ブラウザーがWeb応答を受け入れることができるかどうかを確認する方法が導入されました。 これは、ナビゲーターオブジェクトを介して達成されます-
if (navigator.onLine) {
alert("You are Online");
}else {
alert("You are Offline");
}
オフラインモードは、デバイスが接続されていないか、ユーザーがブラウザーのツールバーからオフラインモードを選択したことを意味します。
ネットワークが利用できないことをユーザーに通知し、WebSocket closeイベントが発生したときに再接続を試みる方法は次のとおりです-
socket.onclose = function (event) {
//Connection closed.
//Firstly, check the reason.
if (event.code != 1000) {
//Error code 1000 means that the connection was closed normally.
//Try to reconnect.
if (!navigator.onLine) {
alert("You are offline. Please connect to the Internet and try again.");
}
}
}
エラーメッセージを受信するためのデモ
次のプログラムは、Webソケットを使用してエラーメッセージを表示する方法を説明します-
<!DOCTYPE html>
<html>
<meta charset = "utf-8"/>
<title>WebSocket Test</title>
<script language = "javascript" type = "text/javascript">
var wsUri = "ws://echo.websocket.org/";
var output;
function init() {
output = document.getElementById("output");
testWebSocket();
}
function testWebSocket() {
websocket = new WebSocket(wsUri);
websocket.onopen = function(evt) {
onOpen(evt)
};
websocket.onclose = function(evt) {
onClose(evt)
};
websocket.onerror = function(evt) {
onError(evt)
};
}
function onOpen(evt) {
writeToScreen("CONNECTED");
doSend("WebSocket rocks");
}
function onClose(evt) {
writeToScreen("DISCONNECTED");
}
function onError(evt) {
writeToScreen('<span style = "color: red;">ERROR:</span> ' + evt.data);
}
function doSend(message) {
writeToScreen("SENT: " + message); websocket.send(message);
}
function writeToScreen(message) {
var pre = document.createElement("p");
pre.style.wordWrap = "break-word";
pre.innerHTML = message; output.appendChild(pre);
}
window.addEventListener("load", init, false);
</script>
<h2>WebSocket Test</h2>
<div id = "output"></div>
</html>
出力は次のとおりです-
WebSocket-メッセージの送受信
通常、サーバーがデータを送信すると、 Message イベントが発生します。 サーバーからクライアントに送信されるメッセージには、プレーンテキストメッセージ、バイナリデータ、または画像を含めることができます。 データが送信されるたびに、 onmessage 関数が起動されます。
このイベントは、サーバーに対するクライアントの耳として機能します。 サーバーがデータを送信するたびに、 onmessage イベントが発生します。
次のコードスニペットは、Web Socketプロトコルの接続を開くことを説明しています。
connection.onmessage = function(e){
var server_message = e.data;
console.log(server_message);
}
また、Web Socketsを使用して転送できるデータの種類を考慮する必要があります。 Webソケットプロトコルは、テキストデータとバイナリデータをサポートしています。 JavaScriptの観点では、 text は文字列を指し、バイナリデータは ArrayBuffer のように表されます。
Webソケットは、一度に1つのバイナリ形式のみをサポートします。 バイナリデータの宣言は、次のように明示的に行われます-
socket.binaryType = ”arrayBuffer”;
socket.binaryType = ”blob”;
文字列
文字列は有用であると考えられ、XMLやJSONなどの人間が読める形式を扱います。 onmessage イベントが発生するたびに、クライアントはデータ型を確認し、それに応じて行動する必要があります。
文字列としてデータ型を決定するためのコードスニペットは以下に記載されています-
socket.onmessage = function(event){
if(typeOf event.data === String ) {
console.log(“Received data string”);
}
}
JSON(JavaScriptオブジェクト表記)
これは、コンピューター間で人間が読み取れるデータを転送するための軽量形式です。 JSONの構造は、キーと値のペアで構成されています。
例
{
name: “James Devilson”,
message: “Hello World!”
}
次のコードは、JSONオブジェクトを処理し、そのプロパティを抽出する方法を示しています-
socket.onmessage = function(event) {
if(typeOf event.data === String ){
//create a JSON object
var jsonObject = JSON.parse(event.data);
var username = jsonObject.name;
var message = jsonObject.message;
console.log(“Received data string”);
}
}
XML
技術はブラウザーごとに異なりますが、XMLの解析は難しくありません。 最良の方法は、jQueryのようなサードパーティライブラリを使用して解析することです。
XMLとJSONの両方で、サーバーは文字列として応答し、クライアント側で解析されます。
ArrayBuffer
構造化されたバイナリデータで構成されます。 位置を簡単に追跡できるように、囲まれたビットは順番に与えられます。 ArrayBufferは画像ファイルを保存するのに便利です。
ArrayBuffersを使用したデータの受信は非常に簡単です。 等号演算子の代わりに演算子 instanceOf が使用されます。
次のコードは、ArrayBufferオブジェクトを処理および受信する方法を示しています-
socket.onmessage = function(event) {
if(event.data instanceof ArrayBuffer ){
var buffer = event.data;
console.log(“Received arraybuffer”);
}
}
デモアプリケーション
次のプログラムコードは、Webソケットを使用してメッセージを送受信する方法を示しています。
<!DOCTYPE html>
<html>
<meta charset = "utf-8"/>
<title>WebSocket Test</title>
<script language = "javascript" type = "text/javascript">
var wsUri = "ws://echo.websocket.org/";
var output;
function init() {
output = document.getElementById("output");
testWebSocket();
}
function testWebSocket() {
websocket = new WebSocket(wsUri);
websocket.onopen = function(evt) {
onOpen(evt)
};
websocket.onmessage = function(evt) {
onMessage(evt)
};
websocket.onerror = function(evt) {
onError(evt)
};
}
function onOpen(evt) {
writeToScreen("CONNECTED");
doSend("WebSocket rocks");
}
function onMessage(evt) {
writeToScreen('<span style = "color: blue;">RESPONSE: ' +
evt.data+'</span>'); websocket.close();
}
function onError(evt) {
writeToScreen('<span style="color: red;">ERROR:</span> ' + evt.data);
}
function doSend(message) {
writeToScreen("SENT: " + message); websocket.send(message);
}
function writeToScreen(message) {
var pre = document.createElement("p");
pre.style.wordWrap = "break-word";
pre.innerHTML = message; output.appendChild(pre);
}
window.addEventListener("load", init, false);
</script>
<h2>WebSocket Test</h2>
<div id = "output"></div>
</html>
出力を以下に示します。
WebSockets-接続を閉じる
*Close* イベントは、サーバーとクライアント間の通信の終了を示します。 *onclose* イベントを使用して、接続を閉じることができます。 *onclose* イベントを使用して通信の終了をマークした後、サーバーとクライアントの間でメッセージをさらに転送することはできません。 同様に、接続不良のためにイベントを閉じることができます。
- close()メソッドは *goodbye handshake の略です。 接続を終了し、接続が再び開かない限り、データを交換することはできません。
前の例と同様に、ユーザーが2番目のボタンをクリックしたときに* close()*メソッドを呼び出します。
var textView = document.getElementById("text-view");
var buttonStop = document.getElementById("stop-button");
buttonStop.onclick = function() {
//Close the connection, if open.
if (socket.readyState === WebSocket.OPEN) {
socket.close();
}
}
以下に示すように、前述のコードと理由のパラメーターを渡すこともできます。
socket.close(1000, "Deliberate disconnection");
次のコードは、Web Socket接続を閉じるまたは切断する方法の完全な概要を示しています-
<!DOCTYPE html>
<html>
<meta charset = "utf-8"/>
<title>WebSocket Test</title>
<script language = "javascript" type = "text/javascript">
var wsUri = "ws://echo.websocket.org/";
var output;
function init() {
output = document.getElementById("output");
testWebSocket();
}
function testWebSocket() {
websocket = new WebSocket(wsUri);
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) {
writeToScreen("CONNECTED");
doSend("WebSocket rocks");
}
function onClose(evt) {
writeToScreen("DISCONNECTED");
}
function onMessage(evt) {
writeToScreen('<span style = "color: blue;">RESPONSE: ' +
evt.data+'</span>'); websocket.close();
}
function onError(evt) {
writeToScreen('<span style = "color: red;">ERROR:</span> '
+ evt.data);
}
function doSend(message) {
writeToScreen("SENT: " + message); websocket.send(message);
}
function writeToScreen(message) {
var pre = document.createElement("p");
pre.style.wordWrap = "break-word";
pre.innerHTML = message;
output.appendChild(pre);
}
window.addEventListener("load", init, false);
</script>
<h2>WebSocket Test</h2>
<div id = "output"></div>
</html>
出力は次のとおりです-
WebSockets-サーバー作業
Web Socketサーバーは単純なプログラムで、Web Socketイベントとアクションを処理する機能があります。 通常、Web SocketクライアントAPIに同様のメソッドを公開し、ほとんどのプログラミング言語は実装を提供します。 次の図は、Web SocketサーバーとWeb Socketクライアント間の通信プロセスを示しており、トリガーされたイベントとアクションを強調しています。
次の図は、Web Socketサーバーとクライアントイベントのトリガーを示しています-
Webサーバーへの接続
Web Socketサーバーは、Web Socketクライアントと同様に機能します。 イベントに応答し、必要に応じてアクションを実行します。 使用されるプログラミング言語に関係なく、すべてのWeb Socketサーバーは特定のアクションを実行します。
Web Socketアドレスに初期化されます。 * OnOpen、OnClose、、および *OnMessage イベントを処理し、クライアントにもメッセージを送信します。
Web Socket Serverインスタンスの作成
すべてのWeb Socketサーバーには、有効なホストとポートが必要です。 サーバーでWeb Socketインスタンスを作成する例は次のとおりです-
var server = new WebSocketServer("ws://localhost:8181");
任意の有効なURLを、以前に使用されていなかったポートの仕様で使用できます。 接続されたクライアントの記録を保存しておくと、さまざまなデータの詳細を提供したり、それぞれに異なるメッセージを送信したりするのに非常に便利です。
Fleckは、 IwebSocketConnection インターフェイスを使用した着信接続(クライアント)を表します。 誰かが当社のサービスに接続または切断するたびに、空のリストを作成または更新できます。
var clients = new List<IWebSocketConnection>();
その後、 Start メソッドを呼び出して、クライアントが接続するのを待つことができます。 起動後、サーバーは着信接続を受け入れることができます。 Fleckでは、Startメソッドには、イベントを発生させたソケットを示すパラメータが必要です-
server.Start(socket) =>
{
});
OnOpenイベント
*OnOpen* イベントは、新しいクライアントがアクセスを要求したことを判断し、初期ハンドシェイクを実行します。 クライアントをリストに追加する必要があり、おそらくIPアドレスなど、それに関連する情報を保存する必要があります。 Fleckは、そのような情報と接続の一意の識別子を提供します。
server.Start(socket) ⇒ {
socket.OnOpen = () ⇒ {
//Add the incoming connection to our list.
clients.Add(socket);
}
//Handle the other events here...
});
OnCloseイベント
*OnClose* イベントは、クライアントが切断されるたびに発生します。 クライアントがリストから削除され、切断について残りのクライアントに通知されます。
socket.OnClose = () ⇒ {
//Remove the disconnected client from the list.
clients.Remove(socket);
};
OnMessageイベント
クライアントがサーバーにデータを送信すると、 OnMessage イベントが発生します。 このイベントハンドラー内では、着信メッセージをクライアントに送信するか、おそらくそれらの一部のみを選択できます。
プロセスは簡単です。 このハンドラは、パラメータとして message という名前の文字列を取ることに注意してください-
socket.OnMessage = () ⇒ {
//Display the message on the console.
Console.WriteLine(message);
};
Send()メソッド
Send()*メソッドは、指定されたクライアントに目的のメッセージを送信するだけです。 Send()を使用すると、テキストデータまたはバイナリデータをクライアント全体に保存できます。
*OnMessage* イベントの動作は次のとおりです-
socket.OnMessage = () ⇒ {
foreach (var client in clients) {
//Send the message to everyone!
//Also, send the client connection's unique identifier in order
//to recognize who is who.
client.Send(client.ConnectionInfo.Id + " says: " + message);
}
};
WebSockets-API
API –定義
APIは、Application Program Interfaceの略で、ソフトウェアアプリケーションを構築するための一連のルーチン、プロトコル、およびツールです。
いくつかの重要な機能は-
- APIは、グラフィカルユーザーインターフェイス(GUI)コンポーネントをプログラミングするときに、ソフトウェアコンポーネントがどのように相互作用し、APIを使用するかを指定します。
- 優れたAPIは、すべての構成要素を提供することにより、プログラムの開発を容易にします。
- 通常HTTPで実行されるRESTは、モバイルアプリケーション、ソーシャルWebサイト、マッシュアップツール、および自動化されたビジネスプロセスでよく使用されます。
- RESTスタイルは、限られた数の操作(動詞)を持つことにより、クライアントとサービス間の対話が強化されることを強調しています。
- リソースを割り当てることで柔軟性が提供されます。独自の一意のユニバーサルリソース識別子(URI)。
- 各動詞には特定の意味(GET、POST、PUT、およびDELETE)があるため、RESTはあいまいさを回避します。
Web Socketの利点
Web Socketは、RESTまたはHTTP全般に関するいくつかの問題を解決します-
双方向
HTTPは、クライアントが常に要求を開始する単方向プロトコルです。 サーバーは応答を処理して返し、クライアントはそれを消費します。 Web Socketは、要求/応答などの事前定義されたメッセージパターンがない双方向プロトコルです。 クライアントまたはサーバーは、相手にメッセージを送信できます。
全二重
HTTPでは、要求メッセージがクライアントからサーバーに送られ、サーバーがクライアントに応答メッセージを送信します。 所定の時間に、クライアントがサーバーと通信するか、サーバーがクライアントと通信します。 Web Socketを使用すると、クライアントとサーバーは互いに独立して通信できます。
単一のTCP接続
通常、HTTP要求に対して新しいTCP接続が開始され、応答が受信された後に終了します。 別のHTTP要求/応答のために、新しいTCP接続を確立する必要があります。 Webソケットの場合、HTTP接続は標準のHTTPアップグレードメカニズムを使用してアップグレードされ、クライアントとサーバーはWebソケット接続のライフサイクルで同じTCP接続を介して通信します。
以下のグラフは、一定のペイロードサイズでN個のメッセージを処理するのにかかった時間(ミリ秒単位)を示しています。
これはこのグラフをフィードする生データです-
上記のグラフと表は、メッセージの数とともにRESTオーバーヘッドが増加することを示しています。 これは、多くのTCP接続を開始および終了する必要があり、多くのHTTPヘッダーを送受信する必要があるためです。
最後の列は、特に、REST要求を実行するための時間の乗算係数を示しています。
2番目のグラフは、ペイロードサイズを変更することにより、一定数のメッセージを処理するのにかかる時間を示しています。
これはこのグラフをフィードする生データです-
このグラフは、RESTエンドポイントの要求/応答の処理の増分コストが最小であり、接続の開始/終了とHTTPセマンティクスの尊重にほとんどの時間が費やされていることを示しています。
結論
Web Socketは低レベルのプロトコルです。 単純な要求/応答設計パターン、リソースの作成/更新/削除方法、ステータスコードなど、すべて その上に構築されます。 これらはすべて、HTTPに対して明確に定義されています。
HTTPはステートレスプロトコルですが、Web Socketはステートフルプロトコルです。 HTTPが水平方向にスケーリングできるのに対し、Webソケット接続は単一サーバー上で垂直方向にスケーリングできます。 Web Socket水平スケーリングには独自のソリューションがいくつかありますが、それらは標準に基づいていません。 HTTPには、キャッシング、ルーティング、多重化などの他の多くの利点があります。 これらはすべて、Web Socketの上に定義する必要があります。
WebSockets-JavaScriptアプリケーション
次のプログラムコードは、JavaScriptおよびWeb Socketプロトコルを使用したチャットアプリケーションの動作を説明しています。
<!DOCTYPE html>
<html lang = "en">
<head>
<meta charset = utf-8>
<title>HTML5 Chat</title>
<body>
<section id = "wrapper">
<header>
<h1>HTML5 Chat</h1>
</header>
<style>
#chat { width: 97%; }
.message { font-weight: bold; }
.message:before { content: ' '; color: #bbb; font-size: 14px; }
#log {
overflow: auto;
max-height: 300px;
list-style: none;
padding: 0;
}
#log li {
border-top: 1px solid #ccc;
margin: 0;
padding: 10px 0;
}
body {
font: normal 16px/20px "Helvetica Neue", Helvetica, sans-serif;
background: rgb(237, 237, 236);
margin: 0;
margin-top: 40px;
padding: 0;
}
section, header {
display: block;
}
#wrapper {
width: 600px;
margin: 0 auto;
background: #fff;
border-radius: 10px;
border-top: 1px solid #fff;
padding-bottom: 16px;
}
h1 {
padding-top: 10px;
}
h2 {
font-size: 100%;
font-style: italic;
}
header, article > * {
margin: 20px;
}
#status {
padding: 5px;
color: #fff;
background: #ccc;
}
#status.fail {
background: #c00;
}
#status.success {
background: #0c0;
}
#status.offline {
background: #c00;
}
#status.online {
background: #0c0;
}
#html5badge {
margin-left: -30px;
border: 0;
}
#html5badge img {
border: 0;
}
</style>
<article>
<form onsubmit = "addMessage(); return false;">
<input type = "text" id = "chat" placeholder = "type and press
enter to chat"/>
</form>
<p id = "status">Not connected</p>
<p>Users connected: <span id = "connected">0
</span></p>
<ul id = "log"></ul>
</article>
<script>
connected = document.getElementById("connected");
log = document.getElementById("log");
chat = document.getElementById("chat");
form = chat.form;
state = document.getElementById("status");
if (window.WebSocket === undefined) {
state.innerHTML = "sockets not supported";
state.className = "fail";
}else {
if (typeof String.prototype.startsWith != "function") {
String.prototype.startsWith = function (str) {
return this.indexOf(str) == 0;
};
}
window.addEventListener("load", onLoad, false);
}
function onLoad() {
var wsUri = "ws://127.0.0.1:7777";
websocket = new WebSocket(wsUri);
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) {
state.className = "success";
state.innerHTML = "Connected to server";
}
function onClose(evt) {
state.className = "fail";
state.innerHTML = "Not connected";
connected.innerHTML = "0";
}
function onMessage(evt) {
//There are two types of messages:
//1. a chat participant message itself
//2. a message with a number of connected chat participants
var message = evt.data;
if (message.startsWith("log:")) {
message = message.slice("log:".length);
log.innerHTML = '<li class = "message">' +
message + "</li>" + log.innerHTML;
}else if (message.startsWith("connected:")) {
message = message.slice("connected:".length);
connected.innerHTML = message;
}
}
function onError(evt) {
state.className = "fail";
state.innerHTML = "Communication error";
}
function addMessage() {
var message = chat.value;
chat.value = "";
websocket.send(message);
}
</script>
</section>
</body>
</head>
</html>
チャットアプリケーションの主要な機能と出力については、以下で説明します-
テストするには、Web Socketがサポートされている2つのウィンドウを開き、上記のメッセージを入力してReturnキーを押します。 これにより、チャットアプリケーションの機能が有効になります。
接続が確立されていない場合、出力は以下のように利用可能です。
成功したチャット通信の出力を以下に示します。
WebSockets-サーバーとの通信
Webは、主にHTTPの要求/応答パラダイムを中心に構築されています。 クライアントがWebページをロードすると、ユーザーが次のページをクリックするまで何も起こりません。 2005年頃、AJAXはWebをより動的に感じるようになりました。 それでも、すべてのHTTP通信はクライアントによって操作されます。これには、サーバーから新しいデータを読み込むためにユーザーの操作または定期的なポーリングが必要です。
新しいデータが利用可能であるとわかった瞬間にサーバーがクライアントにデータを送信できるようにする技術は、かなり前から存在していました。 "Push" や "Comet" などの名前で移動します。
- ロングポーリング*では、クライアントはサーバーへのHTTP接続を開き、応答を送信するまでサーバーを開いたままにします。 サーバーが実際に新しいデータを取得するたびに、サーバーは応答を送信します。 長いポーリングと他のテクニックは非常にうまく機能します。 ただし、これらはすべて1つの問題を共有しており、HTTPのオーバーヘッドを運ぶため、低遅延アプリケーションにはあまり適していません。 たとえば、ブラウザのマルチプレイヤーシューティングゲームや、リアルタイムコンポーネントを備えた他のオンラインゲームです。
ソケットをWebに持ち込む
Web Socket仕様は、Webブラウザーとサーバー間の「ソケット」接続を確立するAPIを定義しています。 簡単に言えば、クライアントとサーバーの間に永続的な接続があり、両方の当事者はいつでもデータの送信を開始できます。
Webソケット接続は、コンストラクターを使用して簡単に開くことができます-
var connection = new WebSocket('ws://html5rocks.websocket.org/echo', ['soap', 'xmpp']);
*ws* は、WebSocket接続の新しいURLスキーマです。 *wss* もあります。これは、安全なHTTP接続に *https* が使用されるのと同じ方法で、安全なWebSocket接続用です。
一部のイベントハンドラを接続にすぐに接続すると、接続が開かれたとき、着信メッセージを受信したとき、またはエラーが発生したときを知ることができます。
2番目の引数は、オプションの subprotocols を受け入れます。 文字列または文字列の配列を指定できます。 各文字列は*サブプロトコル*名を表す必要があり、サーバーは配列で渡された*サブプロトコル*の1つのみを受け入れます。 受け入れられた*サブプロトコル*は、WebSocketオブジェクトのプロトコルプロパティにアクセスすることで決定できます。
//When the connection is open, send some data to the server
connection.onopen = function () {
connection.send('Ping');//Send the message 'Ping' to the server
};
//Log errors
connection.onerror = function (error) {
console.log('WebSocket Error ' + error);
};
//Log messages from the server
connection.onmessage = function (e) {
console.log('Server: ' + e.data);
};
サーバーとの通信
サーバーへの接続が確立されると(openイベントが起動されると)、接続オブジェクトのsend(メッセージ)メソッドを使用してサーバーへのデータ送信を開始できます。 以前は文字列のみをサポートしていましたが、最新の仕様では、バイナリメッセージも送信できるようになりました。 バイナリデータを送信するには、BlobまたはArrayBufferオブジェクトが使用されます。
//Sending String
connection.send('your message');
//Sending canvas ImageData as ArrayBuffer
var img = canvas_context.getImageData(0, 0, 400, 320);
var binary = new Uint8Array(img.data.length);
for (var i = 0; i < img.data.length; i++) {
binary[i] = img.data[i];
}
connection.send(binary.buffer);
//Sending file as Blob
var file = document.querySelector('input[type = "file"]').files[0];
connection.send(file);
同様に、サーバーはいつでもメッセージを送信する場合があります。 これが発生するたびに、onmessageコールバックが起動します。 コールバックはイベントオブジェクトを受け取り、実際のメッセージは `+ data +`プロパティを介してアクセスできます。
WebSocketは、最新の仕様のバイナリメッセージも受信できます。 バイナリフレームは、BlobまたはArrayBuffer形式で受信できます。 受信したバイナリの形式を指定するには、WebSocketオブジェクトのbinaryTypeプロパティを「blob」または「arraybuffer」に設定します。 デフォルトの形式は「blob」です。
//Setting binaryType to accept received binary as either 'blob' or 'arraybuffer'
connection.binaryType = 'arraybuffer';
connection.onmessage = function(e) {
console.log(e.data.byteLength);//ArrayBuffer object if binary
};
WebSocketに新しく追加されたもう1つの機能は拡張機能です。 拡張機能を使用すると、圧縮、多重化などのフレームを送信できます。
//Determining accepted extensions
console.log(connection.extensions);
クロスオリジンコミュニケーション
最新のプロトコルであるため、クロスオリジン通信はWebSocketに直接組み込まれています。 WebSocketは、任意のドメインの関係者間の通信を可能にします。 サーバーは、そのサービスをすべてのクライアントで利用可能にするか、明確に定義されたドメインのセットに存在するクライアントのみで利用可能にするかを決定します。
プロキシサーバー
すべての新しいテクノロジーには、新しい一連の問題が伴います。 WebSocketの場合、ほとんどの企業ネットワークでHTTP接続を仲介するプロキシサーバーとの互換性です。 WebSocketプロトコルは、HTTPアップグレードシステム(通常はHTTP/SSLに使用されます)を使用して、HTTP接続をWebSocket接続に「アップグレード」します。 一部のプロキシサーバーはこれを好まないため、接続を切断します。 したがって、特定のクライアントがWebSocketプロトコルを使用していても、接続を確立できない場合があります。 これにより、次のセクションがさらに重要になります:)
サーバー側
WebSocketを使用すると、サーバー側アプリケーションのまったく新しい使用パターンが作成されます。 LAMPなどの従来のサーバースタックは、HTTP要求/応答サイクルを中心に設計されていますが、多くの場合、開いている多数のWebSocket接続をうまく処理できません。 同時に多数の接続を開いたままにするには、低いパフォーマンスコストで高い同時実行性を受け取るアーキテクチャが必要です。
WebSockets-セキュリティ
プロトコルは、セキュリティ上の理由から設計する必要があります。 WebSocketは最新のプロトコルであり、すべてのWebブラウザーで正しく実装されているわけではありません。 たとえば、それらのいくつかはHTTPとWSの混在をまだ許可していますが、仕様ではその反対を示唆しています。 この章では、ユーザーが知っておくべきいくつかの一般的なセキュリティ攻撃について説明します。
サービス拒否
サービス拒否(DoS)攻撃は、マシンまたはネットワークリソースを要求したユーザーが使用できないようにします。 誰かがWebサーバーに無制限またはわずかな時間間隔で無限数のリクエストを行ったとします。 サーバーは各接続を処理できず、応答を停止するか、応答が遅くなりすぎます。 これは、サービス拒否攻撃と呼ばれます。
サービス拒否は、Webページをロードすることさえできなかったエンドユーザーにとって非常にイライラさせられます。
DoS攻撃はピアツーピア通信にも適用され、P2Pネットワークのクライアントが被害者のWebサーバーに同時に接続するように強制できます。
真ん中の男
例の助けを借りてこれを理解しましょう。
人 A がIMクライアントを介して友人 B とチャットしているとします。 第三者が、あなたが交換したメッセージを見たいと思っています。 だから、彼は両方の人と独立した関係を作ります。 彼はまた、あなたのコミュニケーションの見えない中間体として、人 A と彼の友人 B にメッセージを送信します。 これは、中間者攻撃として知られています。
中間者攻撃は、侵入者がパッケージを直接読み取ることができるため、暗号化されていない接続では簡単です。 接続が暗号化されると、攻撃者が情報を解読する必要がありますが、これは非常に困難です。
技術的な観点から、攻撃者は公開キーメッセージ交換を傍受し、要求されたキーを自分のキーに置き換えながらメッセージを送信します。 明らかに、攻撃者の仕事を難しくする堅実な戦略は、SSHをWebSocketで使用することです。
ほとんどの場合、重要なデータを交換するときは、暗号化されていないWSではなく、WSSの安全な接続を選択します。
XSS
クロスサイトスクリプティング(XSS)は、攻撃者がクライアント側のスクリプトをWebページまたはアプリケーションに挿入できる脆弱性です。 攻撃者は、アプリケーションハブを使用してHTMLまたはJavascriptコードを送信し、クライアントのマシンでこのコードを実行させることができます。
WebSocketネイティブ防御メカニズム
デフォルトでは、WebSocketプロトコルは安全であるように設計されています。 現実の世界では、ユーザーはブラウザの実装が不十分なために発生する可能性のあるさまざまな問題に遭遇する可能性があります。 時間が経つにつれて、ブラウザベンダーは問題をすぐに修正します。
SSH(またはTLS)を介した安全なWebSocket接続が使用される場合、追加のセキュリティ層が追加されます。
WebSocketの世界では、主な懸念事項は安全な接続のパフォーマンスです。 最上部にはまだ追加のTLSレイヤーがありますが、プロトコル自体にはこの種の使用のための最適化が含まれており、さらにWSSはプロキシを介してよりスムーズに動作します。
クライアントからサーバーへのマスキング
WebSocketサーバーとWebSocketクライアント間で送信されるすべてのメッセージには、マスキングキーという名前の特定のキーが含まれています。 仲介者がWebSocketに準拠していない場合、メッセージは影響を受けません。 WebSocketプロトコルを実装するブラウザは、マスキングを処理します。
セキュリティツールボックス
最後に、WebSocketクライアントとサーバー間の情報の流れを調査し、交換されたデータを分析し、起こりうるリスクを特定するための便利なツールを提供できます。
ブラウザ開発ツール
Chrome、Firefox、およびOperaは、開発者のサポートという点で優れたブラウザーです。 それらの組み込みツールは、クライアント側のやり取りとリソースのほぼすべての側面を判断するのに役立ちます。 セキュリティの目的で大きな役割を果たします。
WebSockets-モバイルアプリ
WebSocketは、その名前が示すとおり、Webを使用するものです。 Webは通常、ブラウザページと織り交ぜられています。これは、ブラウザページがデータをオンラインで表示する主な手段だからです。 ただし、ブラウザ以外のプログラムもオンラインデータ送信を使用します。
iPhone(当初)およびiPad(後)のリリースにより、必ずしもWebブラウザを使用せずに、まったく新しいWeb相互接続の世界が導入されました。 代わりに、新しいスマートフォンとタブレットデバイスは、ネイティブアプリの力を利用して独自のユーザーエクスペリエンスを提供しました。
モバイルが重要な理由
現在、アクティブなスマートフォンは10億台あります。 つまり、アプリケーションの何百万人もの潜在的な顧客です。 これらの人々は携帯電話を使用して、毎日のタスクを実行し、インターネットをサーフィンし、通信し、買い物をします。
スマートフォンはアプリの代名詞になりました。 最近では、ユーザーが考えることができるあらゆる用途のアプリがあります。 ほとんどのアプリは、データの取得、トランザクションの実行、ニュースの収集などのためにインターネットに接続します。
既存のWebSocket知識を使用して、スマートフォンまたはタブレットデバイスでネイティブに実行されるWebSocketクライアントを開発することは素晴らしいことです。
ネイティブモバイルアプリとモバイルウェブサイト
さて、これはよくある矛盾であり、いつものように、答えは対象読者のニーズによって異なります。 ユーザーが最新のデザイントレンドに精通している場合、レスポンシブでモバイルフレンドリーなWebサイトをデザインすることが必須になりました。 ただし、エンドユーザーは、従来のデスクトップブラウザーを介した場合と同様に、スマートフォンを介しても、本当に重要なコンテンツに等しくアクセスできることを確認する必要があります。
間違いなく、WebSocket Webアプリは、iOS用のSafariやモバイル用のChromeなどのモバイルブラウザーを含む、HTML5準拠のブラウザーで実行されます。 したがって、スマートフォンとの互換性の問題について心配する必要はありません。
前提条件
スマートフォンアプリを開発するには、開発ツールとSDKのインストールが必要です。
WebSocketは、接続されたモバイルクライアントとタブレットクライアント間でメッセージを送信するためのユニバーサルハブとして機能できます。 HTML5 JavaScriptクライアントのようにWebSocketサーバーと通信するネイティブiOSアプリケーションを実装できます。