WEB通信技術。フロントエンドでSSEロングコネクションを実現し、nodejs+expressでシンプルなサーバーを構築し、インターフェースのデバッグを行い、curlでデータをリクエスト

説明

長時間接続 (Keep-Alive) は、HTTP/1.1 の永続的な接続テクノロジです。これにより、クライアントとサーバーは、1 つの TCP 接続で複数の HTTP 要求と応答を実行できます。要求/応答ごとに新しい接続を確立して切断する必要はありません。長い接続は、サーバーの負荷を軽減し、パフォーマンスを向上させるのに役立ちます。

持続接続のHTTPリクエストメソッドは、通常のHTTPリクエストメソッドと同じで、GET、POST、PUT、DELETEなどのHTTPリクエストメソッドが利用できます。ただし、HTTP 応答を送信する前に、"Connection: keep-alive" 要求ヘッダーを設定して、クライアントがサーバーとの永続的な接続を確立したいことを示す必要があります。Server-Sent Events (略して SSE) は、この問題を解決するために提案された新しい API で、EventSource オブジェクトにデプロイされます。現在、IE を除くすべての主要なブラウザがサポートしています。クライアント(ブラウザ)は HTML5 を使用した EventSource です。
SSE と WebSocket は同様の機能を持ち、どちらもブラウザとサーバー間の通信チャネルを確立するために使用されます。両者の違いは次のとおりです。

  • WebSocket は全二重チャネルであり、双方向で通信でき、より強力な機能を備えています; SSE は、サーバーからブラウザにのみ送信できる一方向チャネルです。

  • WebSocket はサーバー側のサポートを必要とする新しいプロトコルです。SSE は HTTP プロトコルの上に展開され、既存のサーバー ソフトウェアによってサポートされます。

  • SSE は比較的単純な軽量プロトコルであり、WebSocket は比較的複雑で重いプロトコルです。

  • SSE はデフォルトで切断と再接続をサポートしますが、WebSocket には追加のデプロイが必要です。

  • SSE は、送信されるカスタム データ型をサポートします。

上記の比較から、どちらにも独自の特徴があり、さまざまな場面に適していることがわかります。

クライアントコード

接続を確立する

  • まず、ブラウザがサーバーへの接続を開始し、EventSource のインスタンス オブジェクトを生成します。
  • 新しく生成された EventSource インスタンス オブジェクトには、接続の状態を示す readyState 属性があります。

次の値を取ることができます:
0、定数 EventSource.CONNECTING と同等で、接続が確立されていないか、接続が切断されていることを示します。
1. これは定数 EventSource.OPEN と同等であり、接続が確立され、データを受け入れることができることを示します。
2. これは定数 EventSource.CLOSED と同等であり、接続が切断され、再接続されないことを示します。

Open イベント 接続が確立されると、open イベントがトリガーされ、対応するコールバック関数を定義できます。

メッセージ イベントは、データを受信したときにメッセージ イベントをトリガーします。
パラメータ オブジェクト イベントには次の属性があります。
data: サーバーから返されたデータ (テキスト形式)。
origin: サーバー側 URL のドメイン名部分、つまり、プロトコル、ドメイン名、およびポート。
lastEventId: サーバーから送信されたデータのシリアル番号。数値がない場合、このプロパティは空です。

error イベント 通信エラー (接続の中断など) が発生した場合、エラー イベントがトリガーされます。

let source = ''
 if (!!window.EventSource) {
    
    
    source = new EventSource('http://localhost:8088/sses/');
 }
 source.onopen = function(event) {
    
    
   // handle open event
   console.log(source.readyState);
   console.log("长连接打开");
 };
 source.onmessage = function(event) {
    
    
   console.log(event);
   console.log(JSON.parse(event.data));
   console.log(source.readyState);
   console.log("收到长连接信息");
 };
 source.onerror = function(event) {
    
    
   console.log(source.readyState);
   console.log("长连接中断");
   // source.close();
 };

ここに画像の説明を挿入


SSE リクエスト ヘッダーを設定します。

EventSource オブジェクトを使用する場合、要求ヘッダーを設定して追加のパラメーターを指定できます。これらのパラメーターは通常、SSE 要求の処理方法や認証などの操作をサーバーに指示するために使用されます。
要求ヘッダーを設定するには、EventSource オブジェクトの作成時に構成オブジェクトを渡すことができます。次に例を示します。

const eventSource = new EventSource('/sse', {
    
    
  withCredentials: true,
  headers: {
    
    
    'Authorization': 'Bearer xxxxx',
    'X-Custom-Header': 'value'
  }
});

上記のコードでは、withCredentials パラメーターを true に設定し、SSE 要求がクロスドメイン認証情報 (存在する場合) を運ぶことを示します。また、Authorization と X-Custom-Header の 2 つの要求ヘッダーも設定します。これらは、それぞれ認証トークンとカスタム パラメーターを渡すために使用されます。

上記の一般的に使用されるリクエスト ヘッダーに加えて、使用できる他のリクエスト ヘッダーがいくつかあります。次に例を示します。

Last-Event-ID: サーバーが新しいイベントを送信できるように、最後に受信した SSE イベントの ID を指定するために使用されます。
Cache-Control: SSE 要求のキャッシュ ポリシーを制御するために使用されます。
Connection: SSE 要求の接続タイプを指定するために使用され、通常はキープアライブに設定されます。
Accept: クライアントが受け入れることができる SSE データ型を指定するために使用されます。
すべての要求ヘッダーがすべてのブラウザーとサーバーでサポートされているわけではないことに注意してください。ご利用の際は、関連書類をご確認いただき、利用可能かどうかご判断ください。


  • withCredentialsこれは XMLHttpRequest オブジェクトの属性であり、クロスドメイン要求が行われたときに認証情報 (Cookie、HTTP 認証など) を運ぶかどうかを指定するために使用されます。
  • デフォルトでは、セキュリティ リスクを引き起こす可能性があるため、クロスオリジン リクエストは認証情報を伝送しません。ただし、場合によっては、ユーザー認証資格情報をサーバーに送信するなど、クロスドメイン要求で認証情報を運ぶ必要があります。このとき、withCredentials 属性を設定することで、ブラウザーに認証情報を持たせることができます。
  • withCredentialstrue に設定すると、ブラウザーは Cookie フィールドまたは Authorization フィールド (HTTP 認証が使用されている場合) を要求ヘッダーに追加します。このようにして、サーバーは現在のリクエストのユーザーIDを識別し、それに応じて処理できます。サーバーがクロスオリジン要求が認証情報を運ぶことを明示的に許可していない場合でも、ブラウザは認証情報を送信しないことに注意してください。
  • SSE リクエストでは、withCredentials は XMLHttpRequest オブジェクトと同じであり、SSE リクエストがクロスドメイン認証情報を運ぶかどうかを指定するために使用されます。SSE リクエストで認証情報を運ぶ必要がある場合は、withCredentials を true に設定する必要があります。

curl は一般的に使用されるコマンド ライン ツールです。

curl は、HTTP、HTTPS、FTP、SMTP などの複数のプロトコルをサポートする一般的に使用されるコマンド ライン ツールであり、HTTP 要求の送信、ファイルのダウンロード、ファイルのアップロードなどに使用できます。curl は、コマンド ラインから、またはスクリプト内のライブラリとして使用できます。

curl を使用すると、HTTP 要求をサーバーに送信して応答を受信し、その応答をコマンド ラインに表示したり、ファイルに保存したりできます。Curl は、リクエスト ヘッダー、リクエスト メソッド、リクエスト ボディなどの HTTP リクエスト パラメータを設定でき、プロキシ、Cookie、SSL などの機能もサポートします。
ここに画像の説明を挿入

curl を使用して GET 要求を送信し、応答をファイルに保存する例を次に示します。

curl -o response.txt https://example.com

nodejs サーバー

const express = require('express');
const Aixpor = require("./options")
const app = express()
const port = 8088

//设置跨域访问
app.all("*", function(req, res, next) {
    
    
	//设置允许跨域的域名,*代表允许任意域名跨域
	res.header("Access-Control-Allow-Origin", req.headers.origin || '*');
	 // //只允许http://xxx.xx.xx/可跨
    //res.header('Access-Control-Allow-Origin', 'http://xxx.xx.xx/');
	//允许的header类型
	res.header("Access-Control-Allow-Headers", "Content-Type, Authorization, X-Requested-With");
	//跨域允许的请求方式 
	res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
	// 可以带cookies
	res.header("Access-Control-Allow-Credentials", true);
	if (req.method == 'OPTIONS') {
    
    
		res.sendStatus(200);
	} else {
    
    
		next();
	}
})

app.listen(port, () => {
    
    
	console.log(`Example app listening at http://localhost:${
      
      port}`)
})

//实现接口
Aixpor.List(app);
Aixpor.Longstream(app);
//写个接口list
const List = function(app){
    
    
  var data = [{
    
    
		label: '早晨',
		value: '面条'
	},
	{
    
    
		label: '中午',
		value: '煎饼'
	}
];
  app.get('/list', function(req, res) {
    
    
    res.status(200);
    res.json(data);
  });
}

//长连接接口
const Longstream = function(app){
    
    
  var data = [{
    
    
		label: '早晨',
		value: '面条'
	},
	{
    
    
		label: '中午',
		value: '煎饼'
	}
  ];
  app.get('/sses', function(req, res) {
    
    
    res.set({
    
    
      'Content-Type': 'text/event-stream',
      'Cache-Control': 'no-cache',
      'Connection': 'keep-alive'
    });
    // 及时发送刷新响应头
    res.flushHeaders();
    setInterval(() => {
    
    
      const data = {
    
    
        message: `Current time is ${
      
      new Date().toLocaleTimeString()}`
      };
    res.write(`data: ${
      
      JSON.stringify(data)}\n\n`);
    }, 3000);  
  });
}
module.exports = {
    
    List,Longstream}

直接食べられます。

説明: res.flushHeaders()

Node.js では、res.flushHeaders() は、HTTP 応答ヘッダーを手動でフラッシュするためのメソッドです。通常、応答本文を待たずに応答ヘッダーをすぐに送信する必要がある場合に使用されます。これは、大きなファイルのダウンロードやストリーミングを処理する場合など、特定の状況で役立ちます。

Node.js が HTTP リクエストを受信すると、HTTP レスポンスを設定して送信するためのいくつかのプロパティとメソッドを持つ、リクエストに対するレスポンス オブジェクト res が自動的に作成されます。res.flushHeaders() メソッドは、応答本文全体の準備が整うまで待たずに、HTTP 応答ヘッダーをクライアントにすぐに送信します。これにより、クライアントに応答ヘッダーをより速く送信し、クライアントに応答のコンテンツ タイプ、長さなどをより早く知らせることができます。

ストリーミング経由で大きなファイルを送信する res.flushHeaders() メソッドを使用した例を次に示します。

const http = require('http');
const fs = require('fs');

http.createServer(function(req, res) {
    
    
  res.writeHead(200, {
    
    
    'Content-Type': 'application/octet-stream',
    'Content-Disposition': 'attachment; filename=largefile.dat'
  });

  const stream = fs.createReadStream('/path/to/largefile.dat');
  stream.pipe(res);

  // 刷新响应头
  res.flushHeaders();
}).listen(8080);

上記の例では、createReadStream() メソッドを使用して読み取り可能なストリームを作成し、パイプ pipe() メソッドを介して res 応答オブジェクトに接続しました。ファイルの転送を開始する前に、res.writeHead() メソッドを呼び出して HTTP 応答ヘッダーを設定し、転送中に res.flushHeaders() メソッドを呼び出して、HTTP 応答ヘッダーをクライアントにすぐに送信しました。このようにして、クライアントはファイルの種類やサイズなどの情報をより早く知り、ファイルのダウンロードを開始できます。

詳細については、SSE の説明を参照してください。

おすすめ

転載: blog.csdn.net/m0_46672781/article/details/130296397