2011-08-24 7 views
6

PHPとAJAXを使って簡単なWebチャットアプリを作成しようとしています。PHPでログインしたユーザーを追跡する

私は、利用可能なオンラインユーザーの一覧を表示できるように、開いているすべてのセッションに注意する必要があります。チャットセッションを終了し、メッセージを削除するための条件として、「送信側と受信側の両方がオフラインです」を使用するため、ログアウトも認識する必要があります。

データベースのログインユーザーを追跡しています:ログイン時にエントリを追加してログアウト時に削除すると問題はありませんが、ユーザーがログに記録できる2つの方法がありますout:

  • サーバー側のセッションは、非アクティブの後に有効期限が切れます。
  • ブラウザ側でクライアント側のCookieが破棄されます。ある種のoncloseトリガAJAX(ブラウザがクラッシュした場合など)を使用するのは悪い考えです。

最も簡単な解決策は、最後のアクティビティのタイムスタンプを保持しているようです。私は、このかかわらず、いくつかの問題を参照してください:それは正確ではない(と私は3分の間違った有効期限を取得する場合、それはいくつかの男が可能性が3分ですので

  • 私の知る限り、サーバー側の有効期限は、チャンスに基づいています
  • 私は常に、現在の時刻と比較してログインしているすべてのユーザーの最後の活動時間を確認するためにデータベースに問い合わせる必要があります。私はいつどこでこれを効率的にやるのか分かりません。オンラインユーザーのリストが必要なたびにこれを行うのはばかげているようです。

助けてください。私は自分自身をコーディングしています。なぜなら、自分の既存のユーザーデータベースと統合できるWebチャットフレームワークを認識しておらず、私が間違っていると私を修正してしまうからです。

+0

私は、実際にはタイムスタンプを試して推測する必要はないことに気付きました。とにかくすべてのユーザーが常に新しいメッセージを確認するためにクエリを実行するので、クエリが実行されるたびにタイムスタンプを更新し、すべてのタイムスタンプ> 20秒間のユーザーを非アクティブにすることもできます。ですから、古いタイムスタンプを持つエントリをデータベースが自動的に削除する最良の方法を理解する必要があります。 – Jonathan

+0

@bfavaretto注目してくれてありがとう!プログラマーは頼むべき正しい場所のように思えます。 – Jonathan

答えて

0

私はあなたが両方の確率が必要な場合除数はよく分からないが、ここで私は、自動ログアウトの人々に何をすべきかです:

ini_set('session.gc_maxlifetime',3600); // 1 hour 
ini_set('session.gc_probability',1); // it does garbage cleaning EVERY time 
ini_set('session.gc_divisor',1); // it does garbage cleaning EVERY time 
session_start(); 
+0

これは実際には問題ではないことを認識しました。私のOPのコメントを参照してください。しかし、古いエントリをクリーンアップする方法を理解する必要があります。ユーザーがオンラインユーザーリストを要求するたびにクリーンアップが発生しないようにしたいと思います(無駄に見えますが、集中化してサーバー側で行う必要があります)。 – Jonathan

1

私はあなたが多くを行うことができるようになるだろうとは思いませんユーザーがブラウザを閉じてログオフしたかどうかを判断するためにクエリを継続することを軽減するため、インターネット接続の問題などがありますが、各クライアントが5秒ごとにAJAXリクエストをサーバに送信して、サーバー上のアプリケーションは、3〜4回の連続した要求がなかった場合(つまり、最後の処理時間が20秒を超える場合)、ユーザーを「ログオフ」したとみなします。

クライアント側では、クライアントが別のユーザーにメッセージを送信するたびに最後のアクティビティ時間を確認し、発生した場合はログオフしたと応答できます。他のユーザーとチャットを開始しようとした場合は、直ちに電話をかけてステータスを確認することもできます。次に、ユーザーリストのすべてのユーザーのステータスを30秒ごとに確認できます。そうすれば、彼がチャットしている人が予期せずオフラインでドロップした場合、クライアントはかなり迅速なフィードバックを得ることができます。

+0

私は最初の部分に同意しますが、データベースを期限切れのタイムスタンプを内部的に追跡するのが効率的だと思いますが、同時に10人のユーザーに期限切れのタイムスタンプをクリーンアップさせるのは無意味です。 これを行うには、私はcron + mysqlクライアントを使うべきですか、それとも良い方法がありますか? – Jonathan

+1

Cronは問題ありませんが、後で動作を変更したい場合は、DBにアクセスするPHPスクリプトを実行する方が簡単です。 – Ravi

+0

私はRavi、cron + PHPスクリプトに同意します。私はあなたが尋ねてきたので、あなたがcrontabにアクセスしていると仮定していますが、何らかの理由でそうでない場合は、タスクが最後に行われた時間を記録する "貧しい人のcron"実行してから$ x秒が経過した場合はもう一度実行し、すべてのリクエストに対してPHPスクリプトでその関数を実行させます。タスクがいつ実行されるのかを正確に保証することはできないので、正確ではありませんが、ピンチで動作します。私は前にそれをしなければなりませんでした。私がcrontabにアクセスできないときは... –

0

現在使用しているデータのほとんどと必要なデータは、PHPセッションに保存されています。情報からユーザーIDを引き出す方法は明らかではありません。

データベースにバインドされたセッションハンドラを使用すると、すべてが非常に簡単になります。私は素敵なgoogleを持っていました - そこにたくさんの例があります。それらの多く(例:this one)は、セッションを読み戻す際に期限切れをチェックしません。 OTOH私がリンクした例は、ユーザーIDをsesionレコードに追加することを示しています。これは後で必要になります。だから、セッションの読み取りハンドラ関数は次のようなものでなければなりません:

read: 
SELECT session_data, username 
FROM sessions 
WHERE session_id=' . session_id() . ' 
AND last_updated>= ' . date('YmdHis', time()-ini_get('session.gc_maxlifetime')) 

そして、すべての現在のユーザーログオンを取得する:

SELECT username 
FROM sessions 
WHERE last_updated>= ' . date('YmdHis', time()-ini_get('session.gc_maxlifetime')) 

...と出て、自動的にクリア(上書き)セッションガベージコレクタを聞かせて冗長データ。

HTH

0

まず、あなたの懸念事項を分けてください。 「オンラインユーザのリスト」に関する限り、データベース&を使用すると、すでにそれを把握しているようです。 (一部のユーザーが正しくログアウトしなくても、少数の特別なオンラインユーザーを表示しても大きなダメージはありません)

チャットアプリの場合、ユーザーがまだオンラインであるかどうかを確認するには、ajaxを使用する必要があります。 他の方法はありません。もちろん、常にハックがあるかもしれませんが、わかりません。 imageここに答えると(stackoverflow).itは時間が経過したかどうかを常にチェックします(&あなたは新しいものを入力しました)&はコピーを保存します。

1

パターンを反転させて、Ajaxプルの動作をプッシュ通知システムに置き換えることができます。

この方法で、チャットユーザーにログインし、新しいチャットメンバーのログアウトをリアルタイムで通知することができます。実際にこのようなことは一度もしませんでしたが、私はこの種の技術について読んだことがあります。

これはajaxのやり方より少し難しいですが、一度主要な構造が実装されると、機能を簡単に追加でき、パフォーマンスがさらに向上します。

私はそれが役立つことができたいくつかのリンク:

これはjavascriptのチャットを扱うrailscastエピソードで、実装は、レールにあるが、でもレールを理解できない場合は、それをフォローしてコアコンセプトを得ることができます。http://railscasts.com/episodes/260-messaging-with-faye

+0

この回答をお寄せいただきありがとうございます。私はJSのプッシュ通知フレームワークの存在を認識していなかったので、今私は慣れ親しんでおく必要がある新しいものがあります。 :-) –

+0

今のところ私のリーグの外ですが、私はこのことについても気づいていませんでした。私はいつもプッシュの欠如をAJAXの大きな限界と考えていました。素晴らしいことを知っている。 – Jonathan

0

あなたはパフォーマンスを最も懸念しており、実装の詳細がわかっているようです(ほとんど)。セッションを処理するテーブルのタイプを 'メモリ'に変更するだけで、RAMから直接データをフェッチするときに、ほとんどすべての要求に対してdbをクエンチするパフォーマンスを低下させます。ユーザーが明示的にログアウトするたびにセッションを削除するか、ユーザーを非アクティブとしてマークするだけです。

しかし、クライアントとサーバーの間の常時通信を必要とするものを実装することは、HTTPを使って完全に行うことはできません。しかし、合理的なタイムアウトなどを置くと99%の時間がかかるでしょう。

0

私はこのパーティーに遅れていますが、私は2セントを教えてください。

この特定のシナリオでは、悪質な通知のためのプッシュシステムは必要ありません。また、cronは必要ありません。私に説明させてください:

Aay、B、Cはチャットルームにあります。& Bのブラウザがクラッシュしてセッションが終了します。今、サーバーはBがまだそこにあると思っていますが、彼女はそうではありません。どのようにA & Cを更新しますか?更新のためにA & C ASKの場合。 Bの最後のキープアライブタイムスタンプをチェックし、セッションが終了したことを確認します。

すべてA、B & Cがクラッシュした場合、これは起こりません。誰も気にしない?今私たちの間違いを見る人は誰もいません!唯一の欠点は、チャットルームを生きていくことです。これは、別のチャットセッションが作成されたときにクリーンアップすることができます。

最終要旨:

  1. は、アクションが取られた最後の時間のタイムスタンプを保管してください。
  2. ユーザーイベントを使用して、タイムスタンプをループして行き止まりを取り除きます。

ユーザーの場合、これがログアウトされます。チャットルームの場合、これは期限切れのものです。

関連する問題