1. デバッグ対象主に、何をデバッグするのか、最終結果はどうなるのかを知る必要があります。 1. インターフェースをデバッグし、インターフェース アドレスを入力して、対応する結果を取得します。複数のデバイスを同時にデバッグできます。 2. jsapi をデバッグし、対応するメソッドを入力すると、ニュース クライアントに効果が表示されます。 デバッグ インターフェースに関しては、実際に簡単にデバッグする方法がありますが、Android システムとベータ クライアントという 2 つの制限があるため、Chrome ブラウザを介してブリッジします。ただし、この方法は iOS システムおよびクライアントの公式バージョンでは効果がありません。 2. WebSocketの機能WebSocket プロトコルの最大の特徴は、サーバーがクライアントに情報を積極的にプッシュでき、クライアントもサーバーに情報を積極的に送信できることです。これは真の双方向の平等な対話であり、サーバー プッシュ テクノロジの一種です。 その他の機能は次のとおりです: 1. TCP プロトコル上に構築されているため、サーバー側の実装は比較的簡単です。 2. HTTP プロトコルとの互換性が良好です。デフォルトのポートも 80 と 443 であり、ハンドシェイク フェーズでは HTTP プロトコルが使用されるため、ハンドシェイク中にブロックされることは少なく、さまざまな HTTP プロキシ サーバーを通過できます。 3. データ形式は比較的軽量で、パフォーマンスのオーバーヘッドが少なく、通信が効率的です。 4. テキストデータとバイナリデータの両方を送信できます。 5. 同一オリジンの制限がないため、クライアントはどのサーバーとも通信できます。 6. プロトコル識別子は ws (暗号化されている場合は wss) であり、サーバー URL は URL です。 3. ソケット接続を確立するパート 1 で設定したデバッグ目標を達成するために、ここで実装する必要がある関数は次のとおりです。 1. PC は部屋の所有者に相当します。部屋が作成されると、他のデバイスが部屋に入ることができます。1 台のデバイスは 1 つの部屋にしか入室できません。 2. クライアントには切断再接続メカニズムがあります。クライアントが切断された場合、再接続を試みることができます。 3. サーバーはハートビート検出メカニズムを維持します。新しいデバイスが入室したり、以前のデバイスが退室したりすると、現在の部屋のデバイス リストがタイムリーに更新されます。 3.1 部屋の作成方法ブラウザにルーム ID を入力します。ブラウザがサーバーとの Websocket 接続を正常に確立すると、対応する QR コードがブラウザに作成されます。 WeChat/モバイルQQまたはQRコードをスキャンする他のデバイスでスキャンすると、事前に設定されたスキームプロトコルを通じてニュースクライアントの対応するデバッグページにジャンプできます。 クライアントがサーバーとの Websocket 接続を正常に確立すると、ルームへの入室に成功したことになり、対応するアイコンが PC 上に表示されます。 ws.open(サーバーID) .then(() => { // PC が正常に接続を確立した後 setStatus("linked"); // ページのステータスを更新 // QR コードを生成します qrcode(`/tools/index.html#/newslist?serverId=${serverId}`).then(url => { url を設定します。 }); }) .catch(e => { // 接続を確立できませんでした console.error(e); Modal.error({ title: "現在のサーバーに問題があり、修復中です" }); setStatus("リンクを解除"); }); 3.2 クライアント切断再発メカニズムモバイル端末のページには、画面が真っ暗になった場合など、何らかの理由でクライアントがソケット接続を自動的に切断する機能があります。 デバッグを容易にするために、切断後に毎回手動でクリックしたり、ページに再度アクセスしたりする必要はありません。ここでは、単純な切断と再接続のメカニズムを実装しました。 Websocket 接続が切断されると、onclose コールバックが実行されます。したがって、onclose イベントに再接続メカニズムを実装できます。 同時に、無制限の再接続試行を防ぐために、ここでも制限を設定しました。再接続の最大回数は 3 回です。3 回後に再接続されない場合は接続が停止され、再接続が成功すると再接続回数は 3 にリセットされます。 切断する場合: // 切断時 ws.onclose(() => { タイマー = setTimeout(() => { setStatus("リンクを解除"); コードURLを設定します。 }, 500); 再接続番号--; // 再接続回数を制限する if (reconnectNum >= 0) { _open(); //再接続を試みる} }); 接続が成功すると: ws.open(serverId).then(() => { // PC が正常に接続を確立した後 + reconnectNum = 3; +タイマー&& clearTimeout(タイマー); setStatus("linked"); // ページのステータスを更新 // QR コードを生成します qrcode(`/tools/index.html#/newslist?serverId=${serverId}`).then(url => { url を設定します。 }); }); 3.3 ハートビート検出QQ グループでチャットするときと同じように、誰がオンラインであるかは一目でわかります。誰かがチャット グループに参加したり、誰かが退出したりした場合は、ホストに通知し、グループ リストをタイムリーに更新する必要があります。 ハートビート検出には、クライアントによって開始されるハートビート検出とサーバーによって維持されるハートビート検出の 2 つの主なタイプがあります。次の 2 つのタイプを見てみましょう。 1. クライアントによって開始されたハートビート: 一定の間隔で、ping データがサーバーに送信されます。通常の状況では、サーバーはクライアントに pong を返します。クライアントが onmessage イベントを通じてこれを監視できる場合、リクエストが正常であることを意味します。 2. サーバーによって維持されるハートビート: 定期的にすべての接続のステータスを確認します。ステータスが切断されている場合は、リストから削除します。 ここでは、サーバーによって維持されるハートビート検出を使用します。部屋内のデバイスの数が変わると、サーバーは最新のデバイス リストをクライアントにプッシュします。 // クライアントの接続状態を継続的に監視します // 接続が切断された場合は、クライアントをクリアします let aliveClients = new Map(); lastAliveLength = new Map(); 間隔を設定する(() => { クライアントを {} にします。 wss.clients.forEach(関数each(ws) { ws.isAlive が false の場合 ws.terminate() を返します。 } 定数 serverId = ws.serverId; if (クライアント[サーバーID]) { クライアント[サーバーID].push(ws); } それ以外 { クライアント[サーバーID] = [ws]; } ws.isAlive = false; ws.ping(() => {}); }); for (let serverId in クライアント) { aliveClients.set(serverId, クライアント[serverId]); const 長さ = クライアント[サーバーID].長さ; // 現在の serverId に接続されているデバイスの数が変わった場合は、メッセージを送信します if (length !== lastAliveLength.get(serverId)) { // 現在の serverId を持つすべてのデバイスにメッセージを送信します。sendAll("devices", client[serverId], serverId); //現在の serverId の最後の接続数を保存します。lastAliveLength.set(serverId, length); } } 定数サイズ = wss.clients.size; console.log("接続番号: ", サイズ, 新しい Date().toTimeString()); }, 2000); 4. インターフェースをデバッグするセクション 3 では PC とニュース クライアントを正常に接続しましたが、両端の間でデータをどのように通信するのでしょうか。 4.1 インターフェースのデバッグここでは 3 つのフィールドを渡します: 1.serverId: 部屋番号。サーバーは、serverId を持つすべてのメンバーに情報をブロードキャストする必要があります。 2.type: この命令が何を実行するかを入力します。 3.msg: 受信パラメータ。 インターフェースのデバッグ中に渡されるパラメータは次のとおりです。 定数パラメータ = { type: "post", // タイプmsg: { // パラメータ URL: "https://api.prize.qq.com/v1/newsapp/answer/share/oneQ?qID=506336" } }; クライアントがインターフェース要求を正常に完了すると、インターフェース結果、Cookie、デバイス情報が PC に返されます。 // リクエストメソッド const post = url => { if (window.TencentNews && window.TencentNews.post) { window.TencentNews.post(url, {}, window[id], { loginType: "qqorweixin" }, {}); } それ以外の場合 (window.TencentNews && window.TencentNews.postData) { window.TencentNews.postData(url, '{"a":"b"}', id, "requestErrorCallback"); } }; // モバイル端末からサーバーにデータが送信されました ws.send({ type: "postCb", // 実行結果メッセージ: { メソッド: "post", 結果、 クッキー: document.cookie, アプリ情報 } }); このようにして、フロントエンドに結果を表示することができ、それが実際のデータ要求になります。 4.2 履歴記録の保存歴史的記録に関して言えば、私たちの周りの同級生たちは、裁判の過程で依然としてそれを非常に緊急に必要としています。そうしないと、以前のインターフェース アドレスをテストするたびに、それを再入力するか貼り付ける必要があり、非常に不便です。 ユーザーが要求した URL、返された結果、Cookie、デバイス情報などの比較的完全な情報をボスに保存し、履歴 URL のみをローカルに保存します。ユーザーが以前のインターフェイスを再度テストする必要がある場合は、それをクリックするだけです。以前にデバッグしたインターフェースを表示する必要がある場合は、Hawkeye で確認できます。 ローカルストレージは localStorage を使用して行われます。さらに重要なのは、mobx のレスポンシブ ツールも使用しているため、ユーザーがリクエストを完了するとすぐに、サイドの履歴ログで結果を確認できることです。 5. ニュースクライアントでのjsapiのデバッグインターフェースのデバッグに加えて、一部のニュース クライアントで jsapi をデバッグすることもできます。ニュース クライアントの jsapi を呼び出す方法は 2 つあります。 // 直接 window.TencentNews.login("qqorweixin", isLogined => console.log(isLogined)); を呼び出します。 // window.TencentNews.invoke("login", "qqorweixin", isLogined => console.log(isLogined)); を呼び出します。 ここでは、invoke メソッドを使用して jsapi を呼び出すことを選択しました。 PC は jsapi 呼び出しを開始します。 ws.send({ タイプ: "call", メッセージ: { 方法: 方法、 パラメータ: slice.call(引数) } }); モバイル端末はサーバーからのリクエストを受信すると、jsapi を呼び出し、実行結果を PC 端末に返します。 const handleNewsApi = async (msg: any): Promise<any> => { tencentReady() を待機します。 const { メソッド、パラメータ } = msg; 新しいPromiseを返します(resolve => { window.TencentNews.invoke(メソッド、...パラメータ、(結果: 任意) => { 解決({ メソッド、結果 }); }); }); }; 6. 結論この時点で、私の「Websocket ベースのマルチターミナル ブリッジング プラットフォーム」は基本的に構築されました。ただし、簡単に説明する必要がある問題がまだ 2 つあります。 6.1 なぜ serverId を手動で入力する必要があるのですか?最初は、ユーザーがルームを作成すると、システムがランダムに uuid を生成すると考えていましたが、ユーザーがページを更新すると uuid が変わってしまい、以前の uuid に接続できなくなるのではないかと考え、ここで手動入力に切り替えました。 6.2 クライアントからのすべてのソケット要求が同じプロセスに入るようにする方法バックグラウンドで複数のプロセスを使用する場合、ユーザーのリクエストに介入しないと、リクエストへのランダムアクセスが発生し、400 のリクエストが生成されます。結局、最初の接続はプロセス A にあり、リクエストはプロセス B に送信され、プロセス B はそれをどのように処理するかがわかりません。 これを処理するには複数の方法があります。
ここで使用するプラットフォームは、内部デバッグ プラットフォームです。ユーザー数は多くないため、ナットを割るのに大ハンマーを使用する必要はありません。また、マシンは 1 台しかないため、同じ IP が同じプロセスに入ることを考慮します。ここでは、nginx の ip_hash のアイデアを借用します。リクエストがメイン プロセスに到達すると、IP に対して重み付け計算を実行し、プロセスの数に応じて係数を取得します。 もちろん、この方法ではプロセス内のソケット接続が多すぎるという問題もありますが、ユーザー数が多くない場合はまったく問題ありません (この問題に対して、ウォーターフォール フロー メソッドなどの他の方法も検討しました。子プロセスに接続が割り当てられるたびに、まず接続数が最も少ないプロセスが取得され、次にこのプロセスに接続が割り当てられます。ただし、そのたびにテーブルを維持して計算する必要があります)。 6.3 複数プロセス間の通信同じ部屋で、PC側のソケット接続と複数のモバイル端末の接続が同じプロセスで行われない場合、クロスプロセス問題が発生します。極端な例として、各ソケット接続は異なるプロセスにあるため、クライアントにリクエストを送信する必要があることを他のプロセスに通知する方法を検討する必要があります。 私たちのメカニズムを使用する比較的簡単な方法は、各 PC ユーザーがホストとなり、ルームを作成できるようにすることです。モバイル デバイスはルームのメンバーになります。各ルームは独立しており、互いに干渉しません。この方法では、部屋内のすべてのソケット接続を部屋識別子を通じて同じプロセスに配置するため、プロセス間の問題は発生しません。しかし、このアプローチの問題点は、部屋内の接続が多すぎると、他のプロセスがアイドル状態になっている間に、同じプロセスですべての接続を処理する必要があることです。 また、redis を使用することもできます。redis のパブリッシュ/サブスクライブ モードを使用して、現在のプロセス内のルーム ID と情報を他のプロセスにブロードキャストします。他のプロセスは同じルーム ID でソケット接続を持ち、対応する操作を実行します。 上記は、JS が websocket に基づいてマルチターミナル ブリッジング プラットフォームを実装する方法の詳細です。JS の websocket に基づくマルチターミナル ブリッジング プラットフォームの詳細については、123WORDPRESS.COM の他の関連記事に注目してください。 以下もご興味があるかもしれません:
|
<<: MySQL 5.6.23 のインストールと設定環境変数のチュートリアル
>>: Centos7 DockerでNginxファイルを変更するプロセスの詳細な説明
この記事では、MySQL 8.0 のユーザーとロールの管理について例を挙げて説明します。ご参考までに...
1. csvファイルをインポートする次のコマンドを使用します。 1.mysql> infile...
jquery-multiselect (ドロップダウン ボックスをチェックボックス付きの複数選択コン...
目次セーフモード設定テスト1. where句なしで更新および削除する2. 非インデックスキーの削除3...
Linuxでタイムゾーンを変更する場合、常に変更することはできませんAsia/Shanghai に変...
mysql idは1から始まり、不連続なidの問題を解決するために自動的に増加します。強迫性障害の私...
テーブル構造とそのデータをコピーする次のステートメントは、データを新しいテーブルにコピーします。注:...
目次1.kvmの展開1.1 kvmのインストール1.2 kvm Web管理インターフェースのインスト...
6つの効果実装コードhtml <h1>CSS 境界遷移</h1> <セ...
データベースを作成する右クリック - 新しいデータベースを作成ライブラリ名を入力し、文字セットと並べ...
目次フラット化とは何か再帰トストリング減らすアンダーコア_.平坦化_。連合_。違い要約するフラット化...
概要: MySQL のパフォーマンス最適化について話すとき、誰もがクエリ パフォーマンスを向上させる...
この記事の例では、アコーディオン効果を実現するためのVueの具体的なコードを参考までに共有しています...
DataGrid コントロールの DataSource プロパティがデザイン時に設定されている場合、...
MongoDB を起動すると、プロンプトは次のようになります。共有ライブラリのロード中にエラーが発...