PHPチャットの相手の入場時にチャイム鳴動

このQ&Aのポイント
  • PHPのスクリプトを使用して、相手がチャットのページに入場したときにチャイムを鳴動させる方法を知りたいです。
  • 相手側にしか音が鳴らない問題が発生しています。相手がいつ入場したかを確認するために、チャイムを鳴動させたいのですが、どこが間違っているのでしょうか。
  • 質問者はPHPのチャットシステムで、相手がチャットページに入場した時にチャイムを鳴らしたいと考えていますが、自分が先にチャットページを開いていた場合、相手側にしか音が鳴らないという問題が発生しています。解決策を教えてください。
回答を見る
  • ベストアンサー

PHP チャットの相手の入場時にチャイム鳴動

下記のPHPスクリプトで、自分が先にチャットのページを開いていたとして、 相手がチャットのページを開いたら(入場したら)チャイムを鳴動させたいのですが、 相手が入場したときに、相手側にしか音が鳴りません。こちらは、相手がいつ入場したのか わかるために、チャイムを鳴動させたいのですが、どこがどう間違っているのでしょうか。 ご指導よろしくお願い致します --------------------------------------------------------------------------------------------------- /////////////////////////////////////////////////// // IPアドレスをファイルに保存 // /////////////////////////////////////////////////// function reserveIpAdress(){ $filename="ip_log.txt"; if(!filesize($filename)){ // ファイルが空だったら $fp = fopen($filename, 'w'); // 追加書き込み用に、IPログファイルをオープン $buf = $_SERVER['REMOTE_ADDR']."\n"; fwrite($fp, $buf); // IPアドレスを追加書き込み fclose($fp); echo '<audio src="http://5247423.raindrop.jp/chat/music/schjoin.hso" autoplay></audio>'; $_SESSION['ip_write_cnt']++; }else{ $fp = fopen($filename, 'r'); // while(($buf=fgets($fp))===false){ $buf = fgets($fp); // 1行目 // $buf1 = rtrim($buf1); // $buf2 = fgets($fp); // 2行目 fclose($fp); if(rtrim($buf)!==$_SERVER['REMOTE_ADDR']){ // 相手の方が先にチャットにアクセスした時 $fp = fopen($filename, 'a'); $buf2 = $_SERVER['REMOTE_ADDR']."\n"; // 自分のIPアドレスをファイルにライト fwrite($fp, $buf2); fclose($fp); echo '<audio src="http://5247423.raindrop.jp/chat/music/schjoin.hso" autoplay></audio>' }else{ } $_SESSION['ip_write_cnt']++; } } /////////////////////////////// // メインルーチン // /////////////////////////////// session_start(); // セッション開始 if(is_null($_SESSION['ip_write_cnt'])) $_SESSION['ip_write_cnt'] = 0; if($_SESSION['ip_write_cnt']<2){ // 2人でチャットする場合 reserveIpAdress(); // このページにアクセスしたデバイスのIPアドレスをファイルにライト } 以下略

  • PHP
  • 回答数3
  • ありがとう数3

質問者が選んだベストアンサー

  • ベストアンサー
回答No.3

いきなり$_SESSION['user1_flag']なんてのを条件判定に使われても、 そのuser_flag1というセッションデータをどのタイミングでどんな条件でtrueにセットしているのかを 明示してくれないと、それが正しいのかどうかは私には判断できかねます。 ただ、少なくともセッションデータは、ブラウザ間で共有するデータではないので (他人のブラウザでセットした値を参照することはできないので) 他方のブラウザの情報の入手に$_SESSIONを使おうとしているのであれば、 そのこと自体が、誤りだとは思います。 (実際にセットしている部分が不明なので、あくまでも推測ですが) 闇雲にコーディングするのではなく、きちんとロジックを組み立てたほうがよいですよ。 Web上のチャットを含めてWebアプリというのは サーバーとクライアントとのデータのやりとりのみで クライアントとクライアント間で通信することはできません。 このため、別のクライアントの状態を知るには、必ずサーバーを経由させる必要があります。 また、1つの変数の値を、別のクライアントに引き渡すこともできませんので クライアント間で情報を共有するには、 サーバー上のファイルまたはデータベースを使って情報を共有させる必要があります。 よって、まずはCGI(PHP)へのアクセスのたびに、クライアントごとの そのとき入場中の他のクライアントの情報をサーバー上のファイルに記録する 仕組みをまずは作る必要があります。 (ファイル名に自身のIPアドレスを使うなどして、他のクライアントとファイル名が衝突しないようにする) (入場中のクライアントのIPアドレスはチャットのログデータから取り出せる) そのうえで、チャットの閲覧処理部に 1.もし、サーバー上にクライアントの自分自身のIPアドレスがファイル名になった 上記のファイルがあれば、 そのファイルと、今現在入場中の他のクライアントを比較して 増えていれば、チャイムを鳴らすタグを入れる 2.次回のために、現在入場中のクライアントのファイルを自身のIPアドレスをファイル名にして保存する。 3.どんどんファイルが増えていくので、1日?以上経過したファイルは ワイルドカードで削除する仕組みも入れておく。 を入れればよいでしょう。 なお、もし1対1のチャットに限定するのであれば、もっとシンプルにできます。 チャットのリロードでの閲覧処理部に 入場中が自分だけの状態から2人に変化したタイミングを ログファイルから発見できるようにして そこにチャイムのタグを入れればよいだけなので。

beterugius
質問者

お礼

詳しいご回答、どうもありがとうございました。誤解があったことは事実です。superside0さんのご意見をしっかり踏まえたうえで、コーディングし直してみます。

beterugius
質問者

補足

superside0様、大変お世話になりました。$_SESSION変数を皆無にし、 ほとんどの処理をファイル処理にしたところ、おおよそは、思い通りの 動作を実現できました。ありがとうございました。

その他の回答 (2)

回答No.2

> JavaScriptで、chime()関数の中身を作って、監視することになると思うのですが、どういうJavaScriptを書けばよいか皆目思いつきません。 どこまで理解されているのかわからないのと サーバー側がどういう実装なのか分からないので、概念だけになってしまいますが… JavaScriptは、サーバーでなくクライアント(ブラウザ)上で動作しているので サーバからのデータをブラウザで表示が終わったあとで、 だれかが新規に入場したかを知ることはできませんので、 JavaScript”だけ”では サーバー上のデータを監視することはできません。 方法としては、 方法1. リロード時に実行されるCGI自身で、前回の入場中のIPをクライアントごとに記録しておいて それと比較して新規に入場したクライアントがあれば、 チャイムを鳴らすタグをCGIとして生成する。(リロード時にチャイムがなる) 方法2. JavaScript内からサーバーに対して非同期通信(Ajax)で問い合わせし 前回と今回で入場者が増えていればチャイムを鳴らす。 これをJavaScript側でループさせる。 当然、JavaScriptからのAjaxに対して応答するCGIを別途開発する必要がある このとき新規入場がなければ、すぐに応答しないで、入場があるまで 応答を遅らせることで、無駄な通信データを防げる。 またあたかもリアルタイムに入場を監視しているかのような状態に見える。 #これを発展させてチャットメッセージ自体もAjaxで入手すれば #リロードを待たない応答の速いチャットとなる。 が考えられます。

beterugius
質問者

お礼

お忙しいところ、詳しいご回答を頂き、有難うございました。

beterugius
質問者

補足

superside0様のおっしゃるように、自分なりに<body>タグ以降に リロードしたときのための、下記のPHPスクリプトをHTML内に 埋め込んだのですが、チャイムが鳴りません。 どうしたら、先に入場した人に、後から入場してきた人のページ アクセスを知らせるチャイムを鳴動させることができるのでしょうか。 できましたら、具体的なスクリプトを書いて、ご指導お願いでき ませんでしょうか?(ちなみにchime()関数はまだ実装しておりません。) AJAXを利用した場合も、併記していただけると助かります。 -------------------------------------------------------- <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <meta http-equiv="refresh" content="2;url=chatbody.php"> <title>チャット</title> <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script> <script> $(function() { $('html,body').animate({ scrollTop: $('#last').offset().top },'fast'); }); </script> </head> <body text="white" background="./image/mokume2.jpg" onLoad="chime()"> <?php if($_SESSION['user1_flag']===true){ echo '<audio src="http://~/chat/music/schjoin.hso" autoplay></audio>'; $_SESSION['user1_flag'] = false; }elseif($_SESSION['user2_flag']===true){ echo '<audio src="http://~/chat/music/schjoin.hso" autoplay></audio>'; $_SESSION['user2_flag'] = false; } ?> <div style="height: 90px;"> </div> <div id="last"></div> </body> </html>

回答No.1

(1)Aさんはチャット入場済で閲覧中 (2)Bさんのチャット入場処理 これが別々のプロセスで動いています。 (2)の処理にチャイムを鳴らすaudioタグを書いても、当然Bさんにしか聞こえません。 (1)の処理に、だれかが入場したかを監視してチャイムを鳴らす処理を入れる必要があります。 チャットの閲覧処理が、HTMLを定期的にリロードするような原始的なチャットなのか、 それともAJAXを使ったリアルタイム性のあるチャットなのか等で、 実装のアルゴリズムは異なりますが リロード式なら、クライアントIPアドレスごとに前回閲覧時の入場中のIPを記録しておいて、 リロード時にそれと比較して増えていたらチャイムを鳴らすタグを閲覧HTMLに入れればよいでしょう。

beterugius
質問者

お礼

superside0さま、いつもお世話になっております。詳しいご回答どうもありがとうございました。おっしゃる通り実行してみますが、もしまだわからなければ、引き続きご指導よろしくお願い致します。

beterugius
質問者

補足

お世話になります。 superside0様のおっしゃるようにリロード時に閲覧HTMLに<audio>タグを入れるとなると、下記のonLoad=chime() のイベント時に、JavaScriptで、chime()関数の中身を作って、監視することになると思うのですが、どういうJavaScriptを書けばよいか皆目思いつきません。具体的にどう書けばよいのかお教えいただけませんでしょうか。どうぞよろしくお願い致します。もし、JavaScriptで書かないといけないと誤解しているようでしたら、ご指導お願いできますでしょうか。 --------------------------------------------------------- <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <meta http-equiv="refresh" content="2;url=chatbody.php"> <title>チャット</title> <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script> <script> $(function() { $('html,body').animate({ scrollTop: $('#last').offset().top },'fast'); }); </script> </head> <body text="white" background="./image/mokume2.jpg" onLoad="chime()"> <div style="height: 90px;"> </div> <div id="last"></div> </body> </html>

関連するQ&A

  • PHPのチャットアプリでの受信音について

    下記のPHPスクリプトにおいて、左蘭で、氏名とメッセージを入力後、右蘭の メッセージ部分にメッセージが表示されるという仕組みなのですが、自分自身 が書いたメッセージのときにしか音が鳴りません。 本来、他のデバイスで書き込んだ時の受信音が自パソコンで鳴ればいいのですが。 どうすればよいのか教えていただきたいです。 ちなみに、$_SERVER['REMOTE_ADDR'] でIPによる振り分けも行ったのですが、 だめでした。(自パソコンから投稿したときしか音が鳴りませんでした。) ////////////////////////// // ファイルへの書き込み // ////////////////////////// function writeToLogFile($val){ $filename="log.txt"; date_default_timezone_set("Japan"); $date = date('H:i:s'); echo '<audio src="./music/buble.wav" volume="1" autoplay></audio>'; echo '<bgsound src="./music/buble.wav" loop="1" volume="1">'; if($val===1){ // 初回投稿時で、しかも名前とメッセージがある場合(ログファイルが0バイトの場合) $fp = fopen($filename, 'w'); // $log = $_POST['ip_addr']." ".$date." ".$_POST['name']." : ".$_POST['message']; $log = $date." ".$_POST['name']." : ".$_POST['message']; $buf = $log.",\n"; fwrite($fp, $buf); fclose($fp); } elseif($val===2){ // 既に投稿があって、しかも名前とメッセージがある場合(ログファイルのサイズが0バイトでない場合) $fp = fopen($filename, 'a'); $log = $date." ".$_POST['name']." : ".$_POST['message']; $buf = $log.",\n"; fwrite($fp, $buf); fclose($fp); }else{ return; } }

    • 締切済み
    • PHP
  • 何がおかしいのでしょうか?

    $filename1 = 'ymd.dat'; $fp1 = fopen($filename1, "r+"); $day2 = fgets($fp1,9); $day = date('Ymd'); //今日のアクセス数カウント。日付が変われば0になる。 $filename2 = 'ymd2.dat'; $fp2 = fopen($filename2, "r+"); $count2 = fgets($fp2,32); if($day==$day2){ $count2++; fseek($fp1, 0); fputs($fp1, $day); fclose($fp1); }else{ $count2 = 0; fseek($fp1, 0); fputs($fp1, $day); fclose($fp1); } fseek($fp2, 0); fputs($fp2, $count2); fclose($fp2);

    • 締切済み
    • PHP
  • 二重カウント防止

    フリーのカウンタに2重カウントを防止出来るようにいろんなHP見て直したのですが、カウンタ自体動作しなくなりました。どこを直せばよいのでしょうか // 連続カウント防止(yes=1 no=0) $ip_check = 1; //------------ここまで---------- $fp = @fopen($log, "r+") or die($log."が開けません"); $count = fgets($fp, 64); //最大64バイトまで読み込む if(($ip_check == 1 && "$ip" != $_SERVER["REMOTE_ADDR"]) || $ip_check == 0){ $cnt++; $new_data = implode("<>", array($cnt,$_SERVER["REMOTE_ADDR"])); } fseek($fp, 0); //ファイルポインタを先頭に移す flock($fp, 2); //書き込みに対しロック fputs($fp, $count); //ファイルに書き込む fclose($fp); //ファイルをクローズ //桁数のフォーマット $cnt = sprintf(sprintf("%%0%dd", $fig), $count); //画像のサイズオプションを0.gifで取得 $size = getimagesize($path."0.gif"); //IMGタグを出力 for ($i=0; $i<strlen($cnt); $i++): //桁数分だけループ $n = substr($cnt, $i, 1); //左から一桁ずつ取得 echo "<IMG SRC=\"$path$n.gif\" alt=$n $size[3]>"; endfor;?>

    • 締切済み
    • PHP
  • ファイルを読み込んで条件式を満たさない

    ファイルを読み込んで一部の文字列が来たら別のファイルの文字列を書き込んでもらうプログラムを作ろうとしたのですが、何故かifを使って条件分岐を試みたところ分岐してくれません。 どのようにしたら分岐しますか? 出来ればソースもお願いします。 ---ソースの内容--- #include <stdio.h> #include <string.h> void main(void){ FILE *fp,*fp2; char buf[100],buf2[100]; fp=fopen("yasa.txt","r+"); while( fgets( buf, 100, fp ) != NULL ){ if(strcmp(buf,"じゃがいも")==0){ fp2=fopen("kuda.txt","r+"); while( fgets( buf2, 100, fp2 ) != NULL ){ printf("%s",buf2); } fclose(fp2); } else{ printf("%s",buf); } } fclose(fp); } ---ソースここまで--- ---yasa.txtの内容--- きゃべつ にんじん じゃがいも だいこん セロリ ---yasa.txtここまで--- ---kuda.txtの内容--- もも オレンジ みかん ぶどう ---kuda.txtここまで---

  • 続jファイルに文字列を書く

    あれから後一歩と言うところにきました たぶんmallocのバグだと思いますがチャットのシステムを作ろうとしているのですが 読み込み時にエラーになります ソースの注目部分を見てほしいのですが、 注目部分はbuf+1 にすると 文字列が1文字ずつ消えていくバグになり bufにすると 3行目を書き込んだ時点で3行目がの頭の部分の文字列がおかしくなり4行目を書き込もうとするとエラーになります ちゃんと動作するにはどのように書けば良いですか? ---ソース--- #include <stdio.h> void main(void){ FILE *fp; char *tm[1000]; char buf[400]; int i=1,sei; fp= fopen("now.txt","w+"); fprintf(fp,"もも"); fclose(fp); //何で最初に書き込んでるんだ? //という突っ込みがあるでしょうが本当に作りたいプログラムは最初にファイルに書き込まないといけないためです。 fp= fopen("now.txt","r"); while( fgets( buf, 400, fp ) != NULL ){ tm[0]=(char*)malloc(strlen(buf)+1); strcpy(tm[0], buf); } fclose(fp); fp =fopen("moto.txt","r"); while( fgets( buf, 400, fp ) != NULL ){ tm[i] = (char*)malloc(strlen(buf+1)); strcpy(tm[i], buf+1); //ここを注目 if(i<999){ i++; } } fclose(fp); if(i<=1000){ sei=i; } else{ sei=1000; } fp =fopen("moto.txt","w"); for(i=0;i<sei;i++){ if(i==0){ fprintf(fp,"%s\n",tm[0]); } else{ fprintf(fp,"%s",tm[i]); } } } ---now.txt--- もも ---moto.txt--- オレンジ みかん

  • ファイルの内容の表示

    実行時のコマンドライン引数で指定したファイルの内容を、行番号付きで画面に表示するプログラムを作る という問題です。ヒントも与えられています。 行番号付きの表示、コマンドライン引数の利用。両者を組み合わせればできるはずだ >  main関数の引数にargcとargvを指定して、コマンドライン引数をファイル名として利用する。キーボード入力を促す文(プロンプト)や改行チェックは不要なので書かないこと >  コマンドライン引数が指定されない場合は、メッセージを表示してプログラムを終了 >  ファイルの内容を画面表示する処理は、ユーザー定義関数put_file_contentsに記述する。仮引数には文字型のポインタ変数をひとつ指定し、ファイル名を受け渡せるようにする。put_file_contents自体の型は整数型(int)で、正常終了なら返り値0を返すこと。 行番号付きのプログラム#include<stdio.h> > int put_file(char *filename); > > int main() > { > char line[50]; > char *ptr; > > printf("ファイル名を入力:"); > fgets(line,sizeof(line),stdin); > ptr = line + strlen(line) - 1; > if(*ptr == '\n') { > *ptr = '\0'; > } > > put_file(line); > > return 0; > } > > int put_file(char *filename) > { > FILE *fp; > char buf[100]; > int line_no; > > fp = fopen(filename,"r"); > if (fp == NULL){ > printf("%sを開けません\n",filename); > return 1; > } > line_no = 1; > while (fgets(buf,sizeof(buf),fp) != NULL){ > printf("%3d: ",line_no); > printf("%s",buf); > line_no++; > } > fclose(fp); > > return 0; > } で、コマンドライン引数のプログラムは#include<stdio.h> void write_key_inputs(char *filiname); int main(int argc, char *argv[1]) { write_key_inputs(argv[1]); return 0; } void write_key_inputs(char *filename) { FILE *fp; char buf[100] ; fp = fopen(filename,"w"); while(fgets(buf, sizeof(buf),stdin) != NULL) { fputs(buf, fp); } fclose(fp); return ; } です。これらを組み合わせて少しいじると出来るみたいなのですが、できていません。ちなみに私が考えたプログラムは #include<stdio.h> int put_file_contents(char *filename); int main(int argc,char *argv[]) { int i; if(argc == 1){ printf("コマンドライン引数がありません\n"); return 1; } for(i = 0;i<argc;i++) printf("argv[%d]は「%s」です\n",i,argv[i]); put_file(i); return 0; } int put_file(char *filename) { FILE *fp; char buf[100]; int line_no; fp = fopen(filename,"r"); line_no = 1; while (fgets(buf,sizeof(buf),fp) != NULL){ printf("%3d: ",line_no); printf("%s",buf); line_no++; } fclose(fp); return 0; } です。コマンドライン引数は表示されるのですが、行番号が表示されません。どうしたらいいでしょうか??

  • PHPアクセスカウンター

    <?php $filename = 'count.dat'; $fp = fopen($filename, "r+"); $count = fgets($fp,32); $count++; fseek($fp, 0); fputs($fp, $count); fclose($fp); echo ($count); ?> これを日付が変わったら0にリセットしてくれるシステムにしたいんですが、どうしたらいいですか??

    • ベストアンサー
    • PHP
  • C言語のファイル読み込みに関して。

    英文を入力したテキストファイルを読み込むプログラムをつくっているのですが、 ファイル読み込みが上手くできません。 #include<stdio.h> main() { char filename[33]; char sty[512]; FILE *fp; printf("FILENAME: "); fgets(filename, 33, stdin); //読み込むテキストファイルを指定 fp = fopen(filename,"r"); if(fp == NULL){ printf("Can't open the file!\n"); return -1; } fgets(sty, 512, fp); fclose(fp); printf("%s\n",sty); } このプログラムなのですが、どうしても"Can't open the file!"が表示されてしまいます。 どうすればいいのでしょうか?

  • FILE オープンについて

    いつもお世話になります。 今ファイルデータ検索処理を検討しております。 今、search.txtには、 検索対象となるファイルパスが記載されています。 [search.txt] /home/hoge/SAMPLE1.jpg /home/hoge/SAMPLE2.jpg search.txtをfopen()し、1行ずつfgets()して、 得られるファイルパスより、そのファイルを fopen()して解析する処理がしたいですが、 fgets()より得られたファイルパスをfopen()し、 fread()するとセグメンテーションエラーになります。 どのようにしたらいいのでしょうか? 現状のコードを下記します。 FILE *fp; char *com1 = "/home/hoge/search.txt"; FILE *confp; char buf1[1024]; char buf2[1024]; int i =0; fp = fopen(com1, "r"); while( fgets(buf1, sizeof(buf1), fp )){ confp = fopen(buf1, "rb"); //*.JPGファイルをオープン //下記fread()でセグメンテーションエラー size_t size = fread( buf2, sizeof(char), 1024, confp ); for( i = 0; i<1024; i++ ){ if( (buf2[i] == 0xff) && (buf2[i+1] == 0xe0) ){ printf("%02x\n",buf[i+5]); } } } fclose(fp); fclose(confp); 上記のように、search.txtをfopen()し、読み込んだファイルパスを fopen()して、fread()読み込みをする方法を 教えて下さい。 どうぞよろしくお願い致します。

  • どうやってフローチャートを書きますか

    #include<stdio.h>   void main()   {   FILE*fp;   char buf[128];   char *rc;   char fname[20];   do{   printf("file name>>>");   scanf("%s",fname);   fp=fopen(fname,"r");   if=(fp==NULL) printf("File Open Err¥n");   }while(fp==NULL);   rc=fgets(buf,128,fp);   while(rc!=NULL){    printf("%s",buf);    rc=fgets(buf,123,fp);    }    fclose(fp);    }

専門家に質問してみよう