HTTP 長い接続の「サーバー プッシュ」の技術原理については、IBM のこの記事を参照してください。デモを作成しました
1 つ目は、テキスト入力とチャット コンテンツを表示する iframe を含むホームページです。 、および非表示の iframe がフォームの送信に使用されます:
コードは次のとおりです:
<?php //chat.php header('cache-control: private'); header('Content-Type: text/html; charset=utf-8'); ?> <html> <script type="text/javascript"> function submitChat(obj) { obj.submit(); document.getElementsByName('content')[0].value = ''; } </script> <iframe src="./chat_content.php" height="300" width="100%"></iframe> <iframe name="say" height="0" width="0"></iframe> <form method="POST" target="say" action="./say.php" onsubmit="submitChat(this)"> <input type="text" size="30" name="content" /> <input type="button" value="say" onclick="submitChat(this.form)" /> </form> </html>
もう 1 つは、ユーザーが送信したチャットの内容をロックせずに単に書き込むことです。単純なバージョンです:
コードは次のとおりです:
<?php $content = trim($_POST['content']); if ($content) { $fp = fopen('./chat.txt', 'a'); fwrite($fp, $content . "\n"); fclose($fp); clearstatcache(); } ?>
次に、メインのHTTP長い接続部分、chat_content.phpファイルを見てみましょう:
コードは次のとおりです:
<?php header('cache-control: private'); header('Content-Type: text/html; charset=utf-8'); //测试设置30秒超时,一般会设置比较长时间。 set_time_limit(30); //这一行是为了搞定IE这个BT echo str_repeat(' ', 256); ob_flush(); flush(); $fp = new SplFileObject('./chat.txt', 'r+'); $line = 0; $totalLine = 0; while (!$fp->eof()) { $fp->current(); $totalLine++; $fp->next(); } $fp->seek($totalLine); $i = $totalLine - 1; while (true) { if (!$fp->eof()) { if ($content = trim($fp->current())) { echo '<div>'; echo htmlspecialchars($content); echo "</div>"; flush(); $fp->next(); $i++; } } else { $fp->seek($i - 1); $fp->next(); } { //这里可以添加心跳检测后退出循环 } usleep(1000); } ?>
説明します
06. 長時間の HTTP 接続の維持には確実に時間がかかり、おそらく数時間かかるため、タイムアウトを設定します。上記の記事では、次の 2 つだけについても説明しています。このような長い HTTP 接続は、ブラウザの制限により開くことができます。また、タイムアウトなしを設定した場合でも、サーバー部分(Apacheなど)の設定ファイルでHTTPリクエストの最大待ち時間が設定されている場合もあるため、一般的にはデフォルトでの効果が期待できない場合があります。 15分のタイムアウト。興味があれば、自分で変更してみることもできます。
09. ここで空白のセクションが出力されます。これは主にマニュアルで IE ブラウザが最初の 256 文字を直接出力しないと説明されているためです。そのため、最初に空白を出力して、その後の内容を出力できるようにしているのかもしれません。他のブラウザにも他のブラウザ用の設定があります。詳細については、PHP マニュアルの frush 関数の説明を確認してください。次の 11 行と 12 行は、これらの空白文字をブラウザに強制的に出力させるためのものです。
13. ~ 20. ここでの主な目的は、この行の終わりから内容を読み取ることができるようにファイルの行数を計算することです。
次の while ループは、ファイルの内容をループで出力するたびに、ユーザーがファイルに書き込む場合、現在の検出は終わりではありません。ファイルの行が読み取られて出力されます。それ以外の場合は、ポインタを 1 行進めてループを継続し、毎回 1000 マイクロ秒待機します。
39サーバーはクライアントが切断されたことを認識していない可能性があるため、たとえば、各ユーザーはハートビート フラグを保持し、最後のハートビート時間が検出されたときに、数秒ごとに最新のハートビート時間を更新する必要がある場合があります。長期間更新されなかった場合、無限ループが開始され、HTTP 接続が閉じられます。