検索
ホームページウェブフロントエンドjsチュートリアルNode と React でリアルタイムに通信するにはどうすればよいですか?

Node と React でリアルタイムに通信するにはどうすればよいですか?

#チュートリアルの推奨事項:

node js チュートリアルReact チュートリアルWebSocket チュートリアル

Web は、クライアントとサーバー間の全二重 (または双方向) 通信をサポートするために長い道のりを歩んできました。これが WebSocket プロトコルの主な目的であり、単一の TCP ソケット接続を介してクライアントとサーバー間の永続的なリアルタイム通信を提供することです。

WebSocket プロトコルには 2 つのアジェンダしかありません。1) ハンドシェイクを開始すること、2) データ転送を支援することです。サーバーとクライアントのハンドシェイクが成功すると、ほとんどオーバーヘッドなく相互にデータを自由に送信できるようになります。

WebSocket 通信は、WS (ポート 80) または WSS (ポート 443) プロトコルを使用して、単一の TCP ソケット上で行われます。

Can I Use によると、この記事の執筆時点では、Opera Mini を除くほぼすべてのブラウザが WebSocket をサポートしています。

現在の状況

これまで、リアルタイム データ通信を必要とする Web アプリケーション (ゲームやチャット アプリケーションなど) を作成するには、

HTTP プロトコルを悪用して の 2 つを確立する必要がありました。データ転送の方法。リアルタイム機能を実装する方法は数多くありますが、WebSocket ほど効率的なものはありません。 HTTP ポーリング、HTTP ストリーミング、Comet、SSE - それらにはすべて欠点があります。

HTTP ポーリング

問題を解決する最初の試みは、サーバーを定期的にポーリングすることです。 HTTP ロングポーリングのライフサイクルは次のとおりです。

    クライアントはリクエストを作成し、応答を待ちます。
  1. サーバーは、変更、更新、またはタイムアウトが発生するまで応答を遅らせます。サーバーがクライアントに何かを返すまで、リクエストは「保留中」のままになります。
  2. サーバー側で何らかの変更または更新があると、サーバー側は応答をクライアントに送り返します。
  3. クライアントは、次の変更セットをリッスンするために新しいロング ポーリング リクエストを送信します。
ロングポーリングには、ヘッダーのオーバーヘッド、遅延、タイムアウト、キャッシュなど、多くの脆弱性があります。

HTTP ストリーミング

このメカニズムにより、最初のリクエストが無期限にオープンされたままになるため、ネットワーク遅延の苦痛が軽減されます。サーバーがデータをプッシュした後でも、リクエストは終了しません。 HTTP フローのライフサイクル メソッドの最初の 3 つのステップは、HTTP ポーリングの場合と同じです。

ただし、応答がクライアントに返されるとき、要求は決して終了せず、サーバーは接続を開いたままにして、変更が発生したときに新しい更新を送信します。

サーバー送信イベント (SSE)

SSE を使用して、サーバーはデータをクライアントにプッシュします。チャットまたはゲーム アプリケーションは SSE に完全に依存することはできません。 SSE の最適な使用例は、Facebook のニュース フィードのようなものです。新しい投稿が公開されるたびに、サーバーはそれをタイムラインにプッシュします。 SSE は従来の HTTP 経由で送信され、オープン接続の数には制限があります。

これらの方法は非効率であるだけでなく、それらを保守するためのコードも開発者にとって面倒なものです。

WebSocket

WebSocket は、既存の双方向通信テクノロジを置き換えるように設計されています。上で説明した既存の方法は、全二重リアルタイム通信に関しては信頼性も効率性もありません。

WebSocket は SSE に似ていますが、クライアントからサーバーにメッセージを戻すのにも優れています。データは単一の TCP ソケット接続を介して提供されるため、接続の制限は問題になりません。


実践的なチュートリアル

冒頭で述べたように、WebSocket プロトコルには 2 つのアジェンダしかありません。 WebSocket がこれらのアジェンダをどのように実装するかを見てみましょう。これを行うために、Node.js サーバーをプロファイリングし、React.js で構築されたクライアントに接続します。

議題 1: WebSocket はサーバーとクライアント間のハンドシェイクを確立します

サーバー レベルでのハンドシェイクの作成

単一のポートを使用して、HTTP サービスと WebSocket サービスをそれぞれ提供できます。以下のコードは、単純な HTTP サーバーの作成を示しています。作成したら、WebSocket サーバーを HTTP ポートにバインドします。

const webSocketsServerPort = 8000;
const webSocketServer = require('websocket').server;
const http = require('http');
// Spinning the http server and the websocket server.
const server = http.createServer();
server.listen(webSocketsServerPort);
const wsServer = new webSocketServer({
  httpServer: server
});

WebSocket サーバーを作成した後、クライアントからリクエストを受信するときにハンドシェイクを受け入れる必要があります。接続されているすべてのクライアントをコード内のオブジェクトとして保存し、ブラウザーからリクエストを受信するときに一意のユーザー ID を使用します。

// I'm maintaining all active connections in this object
const clients = {};

// This code generates unique userid for everyuser.
const getUniqueID = () => {
  const s4 = () => Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1);
  return s4() + s4() + '-' + s4();
};

wsServer.on('request', function(request) {
  var userID = getUniqueID();
  console.log((new Date()) + ' Recieved a new connection from origin ' + request.origin + '.');
  // You can rewrite this part of the code to accept only the requests from allowed origin
  const connection = request.accept(null, request.origin);
  clients[userID] = connection;
  console.log('connected: ' + userID + ' in ' + Object.getOwnPropertyNames(clients))
});

それでは、接続が受け入れられると何が起こるでしょうか?

接続を確立するために通常の HTTP リクエストを送信するとき、クライアントはリクエスト ヘッダーで

*Sec-WebSocket-Key* を送信します。サーバーはこの値をエンコードしてハッシュし、事前定義された GUID を追加します。これは、サーバーによって送信されたハンドシェイクの *Sec-WebSocket-Accept* で生成された値で応答します。

リクエストがサーバーで受け入れられると (必要な検証の後)、ハンドシェイクはステータス コード

101 で完了します。ブラウザにステータス コード 101 以外のものが表示された場合は、WebSocket のアップグレードが失敗し、通常の HTTP セマンティクスが適用されることを意味します。

*Sec-WebSocket-Accept* 头字段指示服务器是否愿意接受连接。此外如果响应缺少 *Upgrade* 头字段,或者 *Upgrade* 不等于 websocket,则表示 WebSocket 连接失败。

成功的服务器握手如下所示:

HTTP GET ws://127.0.0.1:8000/ 101 Switching Protocols
Connection: Upgrade
Sec-WebSocket-Accept: Nn/XHq0wK1oO5RTtriEWwR4F7Zw=
Upgrade: websocket

在客户端级别创建握手

在客户端,我使用与服务器中的相同 WebSocket 包来建立与服务器的连接(Web IDL 中的 WebSocket API 正在由W3C 进行标准化)。一旦服务器接受请求,我们将会在浏览器控制台上看到 WebSocket Client Connected

这是创建与服务器的连接的初始脚手架:

import React, { Component } from 'react';
import { w3cwebsocket as W3CWebSocket } from "websocket";

const client = new W3CWebSocket('ws://127.0.0.1:8000');

class App extends Component {
  componentWillMount() {
    client.onopen = () => {
      console.log('WebSocket Client Connected');
    };
    client.onmessage = (message) => {
      console.log(message);
    };
  }
  
  render() {
    return (
      <div>
        Practical Intro To WebSockets.
      </div>
    );
  }
}

export default App;

客户端发送以下标头来建立握手:

HTTP GET ws://127.0.0.1:8000/ 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: vISxbQhM64Vzcr/CD7WHnw==
Origin: http://localhost:3000
Sec-WebSocket-Version: 13

现在客户端和服务器通过相互握手进行了连接,WebSocket 连接可以在接收消息时传输消息,从而实现 WebSocket 协议的第二个议程。

议程2:实时信息传输

Node と React でリアルタイムに通信するにはどうすればよいですか?

我将编写一个基本的实时文档编辑器,用户可以将它们连接在一起并编辑文档。我跟踪了两个事件:

  1. 用户活动:每次用户加入或离开时,我都会将消息广播给所有连接其他的客户端。
  2. 内容更改:每次修改编辑器中的内容时,都会向所有连接的其他客户端广播。

该协议允许我们用二进制数据或 UTF-8 发送和接收消息(注意:传输和转换 UTF-8 的开销较小)。

只要我们对套接字事件onopenoncloseonmessage有了充分的了解,理解和实现 WebSockets 就非常简单。客户端和服务器端的术语相同。

在客户端发送和接收消息

在客户端,当新用户加入或内容更改时,我们用 client.send 向服务器发消息,以将新信息提供给服务器。

/* When a user joins, I notify the
server that a new user has joined to edit the document. */
logInUser = () => {
  const username = this.username.value;
  if (username.trim()) {
    const data = {
      username
    };
    this.setState({
      ...data
    }, () => {
      client.send(JSON.stringify({
        ...data,
        type: "userevent"
      }));
    });
  }
}

/* When content changes, we send the
current content of the editor to the server. */
onEditorStateChange = (text) => {
 client.send(JSON.stringify({
   type: "contentchange",
   username: this.state.username,
   content: text
 }));
};

我们跟踪的事件是:用户加入和内容更改。

从服务器接收消息非常简单:

componentWillMount() {
  client.onopen = () => {
   console.log(&#39;WebSocket Client Connected&#39;);
  };
  client.onmessage = (message) => {
    const dataFromServer = JSON.parse(message.data);
    const stateToChange = {};
    if (dataFromServer.type === "userevent") {
      stateToChange.currentUsers = Object.values(dataFromServer.data.users);
    } else if (dataFromServer.type === "contentchange") {
      stateToChange.text = dataFromServer.data.editorContent || contentDefaultMessage;
    }
    stateToChange.userActivity = dataFromServer.data.userActivity;
    this.setState({
      ...stateToChange
    });
  };
}

在服务器端发送和侦听消息

在服务器中,我们只需捕获传入的消息并将其广播到连接到 WebSocket 的所有客户端。这是臭名昭着的 Socket.IO 和 WebSocket 之间的差异之一:当我们使用 WebSockets 时,我们需要手动将消息发送给所有客户端。  Socket.IO 是一个成熟的库,所以它自己来处理。

const sendMessage = (json) => {
  // We are sending the current data to all connected clients
  Object.keys(clients).map((client) => {
    clients[client].sendUTF(json);
  });
}

connection.on(&#39;message&#39;, function(message) {
    if (message.type === &#39;utf8&#39;) {
      const dataFromClient = JSON.parse(message.utf8Data);
      const json = { type: dataFromClient.type };
      if (dataFromClient.type === typesDef.USER_EVENT) {
        users[userID] = dataFromClient;
        userActivity.push(`${dataFromClient.username} joined to edit the document`);
        json.data = { users, userActivity };
      } else if (dataFromClient.type === typesDef.CONTENT_CHANGE) {
        editorContent = dataFromClient.content;
        json.data = { editorContent, userActivity };
      }
      sendMessage(JSON.stringify(json));
    }
  });

将消息广播到所有连接的客户端。

Node と React でリアルタイムに通信するにはどうすればよいですか?

浏览器关闭后会发生什么?

在这种情况下,WebSocket调用 close 事件,它允许我们编写终止当前用户连接的逻辑。在我的代码中,当用户离开文档时,会向其余用户广播消息:

connection.on(&#39;close&#39;, function(connection) {
    console.log((new Date()) + " Peer " + userID + " disconnected.");
    const json = { type: typesDef.USER_EVENT };
    userActivity.push(`${users[userID].username} left the document`);
    json.data = { users, userActivity };
    delete clients[userID];
    delete users[userID];
    sendMessage(JSON.stringify(json));
  });

该应用程序的源代码位于GitHub上的 repo 中。

结论

WebSockets 是在应用中实现实时功能的最有趣和最方便的方法之一。它为我们提供了能够充分利用全双工通信的灵活性。我强烈建议在尝试使用 Socket.IO 和其他可用库之前先试试 WebSockets。

编码快乐!

更多编程相关知识,请访问:编程教学!!

以上がNode と React でリアルタイムに通信するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明
この記事はsegmentfaultで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。
JavaScriptとWeb:コア機能とユースケースJavaScriptとWeb:コア機能とユースケースApr 18, 2025 am 12:19 AM

Web開発におけるJavaScriptの主な用途には、クライアントの相互作用、フォーム検証、非同期通信が含まれます。 1)DOM操作による動的なコンテンツの更新とユーザーインタラクション。 2)ユーザーエクスペリエンスを改善するためにデータを提出する前に、クライアントの検証が実行されます。 3)サーバーとのリフレッシュレス通信は、AJAXテクノロジーを通じて達成されます。

JavaScriptエンジンの理解:実装の詳細JavaScriptエンジンの理解:実装の詳細Apr 17, 2025 am 12:05 AM

JavaScriptエンジンが内部的にどのように機能するかを理解することは、開発者にとってより効率的なコードの作成とパフォーマンスのボトルネックと最適化戦略の理解に役立つためです。 1)エンジンのワークフローには、3つの段階が含まれます。解析、コンパイル、実行。 2)実行プロセス中、エンジンはインラインキャッシュや非表示クラスなどの動的最適化を実行します。 3)ベストプラクティスには、グローバル変数の避け、ループの最適化、constとletsの使用、閉鎖の過度の使用の回避が含まれます。

Python vs. JavaScript:学習曲線と使いやすさPython vs. JavaScript:学習曲線と使いやすさApr 16, 2025 am 12:12 AM

Pythonは、スムーズな学習曲線と簡潔な構文を備えた初心者により適しています。 JavaScriptは、急な学習曲線と柔軟な構文を備えたフロントエンド開発に適しています。 1。Python構文は直感的で、データサイエンスやバックエンド開発に適しています。 2。JavaScriptは柔軟で、フロントエンドおよびサーバー側のプログラミングで広く使用されています。

Python vs. JavaScript:コミュニティ、ライブラリ、リソースPython vs. JavaScript:コミュニティ、ライブラリ、リソースApr 15, 2025 am 12:16 AM

PythonとJavaScriptには、コミュニティ、ライブラリ、リソースの観点から、独自の利点と短所があります。 1)Pythonコミュニティはフレンドリーで初心者に適していますが、フロントエンドの開発リソースはJavaScriptほど豊富ではありません。 2)Pythonはデータサイエンスおよび機械学習ライブラリで強力ですが、JavaScriptはフロントエンド開発ライブラリとフレームワークで優れています。 3)どちらも豊富な学習リソースを持っていますが、Pythonは公式文書から始めるのに適していますが、JavaScriptはMDNWebDocsにより優れています。選択は、プロジェクトのニーズと個人的な関心に基づいている必要があります。

C/CからJavaScriptへ:すべてがどのように機能するかC/CからJavaScriptへ:すべてがどのように機能するかApr 14, 2025 am 12:05 AM

C/CからJavaScriptへのシフトには、動的なタイピング、ゴミ収集、非同期プログラミングへの適応が必要です。 1)C/Cは、手動メモリ管理を必要とする静的に型付けられた言語であり、JavaScriptは動的に型付けされ、ごみ収集が自動的に処理されます。 2)C/Cはマシンコードにコンパイルする必要がありますが、JavaScriptは解釈言語です。 3)JavaScriptは、閉鎖、プロトタイプチェーン、約束などの概念を導入します。これにより、柔軟性と非同期プログラミング機能が向上します。

JavaScriptエンジン:実装の比較JavaScriptエンジン:実装の比較Apr 13, 2025 am 12:05 AM

さまざまなJavaScriptエンジンは、各エンジンの実装原則と最適化戦略が異なるため、JavaScriptコードを解析および実行するときに異なる効果をもたらします。 1。語彙分析:ソースコードを語彙ユニットに変換します。 2。文法分析:抽象的な構文ツリーを生成します。 3。最適化とコンパイル:JITコンパイラを介してマシンコードを生成します。 4。実行:マシンコードを実行します。 V8エンジンはインスタントコンピレーションと非表示クラスを通じて最適化され、Spidermonkeyはタイプ推論システムを使用して、同じコードで異なるパフォーマンスパフォーマンスをもたらします。

ブラウザを超えて:現実世界のJavaScriptブラウザを超えて:現実世界のJavaScriptApr 12, 2025 am 12:06 AM

現実世界におけるJavaScriptのアプリケーションには、サーバー側のプログラミング、モバイルアプリケーション開発、モノのインターネット制御が含まれます。 2。モバイルアプリケーションの開発は、ReactNativeを通じて実行され、クロスプラットフォームの展開をサポートします。 3.ハードウェアの相互作用に適したJohnny-Fiveライブラリを介したIoTデバイス制御に使用されます。

next.jsを使用してマルチテナントSaaSアプリケーションを構築する(バックエンド統合)next.jsを使用してマルチテナントSaaSアプリケーションを構築する(バックエンド統合)Apr 11, 2025 am 08:23 AM

私はあなたの日常的な技術ツールを使用して機能的なマルチテナントSaaSアプリケーション(EDTECHアプリ)を作成しましたが、あなたは同じことをすることができます。 まず、マルチテナントSaaSアプリケーションとは何ですか? マルチテナントSaaSアプリケーションを使用すると、Singの複数の顧客にサービスを提供できます

See all articles

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

PhpStorm Mac バージョン

PhpStorm Mac バージョン

最新(2018.2.1)のプロフェッショナル向けPHP統合開発ツール

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

Eclipse を SAP NetWeaver アプリケーション サーバーと統合します。

SublimeText3 英語版

SublimeText3 英語版

推奨: Win バージョン、コードプロンプトをサポート!

AtomエディタMac版ダウンロード

AtomエディタMac版ダウンロード

最も人気のあるオープンソースエディター

Dreamweaver Mac版

Dreamweaver Mac版

ビジュアル Web 開発ツール