早速今朝この目覚ましで起きたら異常に目覚めが良くて7時前に会社に着いちゃった。
始業2時間前。アホだ。

で、前回の続きなわけだけど、サーバを作るなんて高等技術は俺には無いから、当然誰か偉い人が書いたプログラムをパクる。

「サーバを作る C言語」でググって見つけた、68user's page様の、
「ネットワークプログラミングの基礎知識 >> C 言語で echo サーバを作ってみよう (1)」
にあるソースを元に、今回の目的のサーバを作る。

やりたいことは簡単。

任意のポートで待って、接続されたら
kill `pidof mpg123`
を実行する。

シンプルにこんだけ。
これに、成功したかどうかを返すよーな親切機能を付け加えたりするのは気分次第。

こいつは、stop_mp3_serverと名付けよう。

stop_mp3_server.c

/************************************************************************
* Name : stop_mp3_server.c
*
* Action: ****番ポートで待ち受けて、接続があったらmpg123をkillする。
*
*       2007.06.14 Ver.0.01 Genki edit.
*       refer to echo-server-1.c by
*       http://x68000.q-e-d.net/~68user/net/c-echo-1.html
*           
*
*   Ver.0.01  とりあえずAction通りに動く。
*       結果によってsuccess or errorを返す。
************************************************************************
* Origin
* $Id: echo-server-1.c,v 1.6 2005/02/19 16:01:53 68user Exp $
*
* echo サーバサンプル
*
* written by 68user http://X68000.q-e-d.net/~68user/
************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/uio.h>
#include <unistd.h>
#include <sys/param.h>
#include <netinet/in.h>
#include <arpa/inet.h>


int main(int argc, char *argv[]){
  int connected_socket, listening_socket;
  struct sockaddr_in sin;
  int len, ret;
  int sock_optval = 1;
  int port = ****;
        /* リスニングソケットを作成 */
  listening_socket = socket(AF_INET, SOCK_STREAM, 0);
  if ( listening_socket == -1 ){
    perror("socket");
    exit(1);
  }
        /* ソケットオプション設定 */
  if ( setsockopt(listening_socket, SOL_SOCKET, SO_REUSEADDR,
      &sock_optval, sizeof(sock_optval)) == -1 ){
  perror("setsockopt");
    exit(1);
  }
        /* アドレスファミリ・ポート番号・IPアドレス設定 */
  sin.sin_family = AF_INET;
  sin.sin_port = htons(port);
  sin.sin_addr.s_addr = htonl(INADDR_ANY);

        /* ソケットにアドレス(=名前)を割り付ける */
  if ( bind(listening_socket, (struct sockaddr *)&sin, sizeof(sin)) < 0 ){
  perror("bind");
    exit(1);
  }
        /* ポートを見張るよう、OS に命令する */
  ret = listen(listening_socket, SOMAXCONN);
  if ( ret == -1 ){
  perror("listen");
    exit(1);
  }
  printf("ポート %d を見張ります。\n", port);


  struct hostent *peer_host;
  struct sockaddr_in peer_sin;

  len = sizeof(peer_sin);
        /* コネクション受け付け */
  connected_socket = accept(listening_socket, (struct sockaddr *)&peer_sin, &len);
  if ( connected_socket == -1 ){
    perror("accept");
      exit(1);
  }

  /* ここから Genki wrote */
  
  if(!system("kill `pidof mpg123`")){
    write(connected_socket,"success",7);
  }else{
    write(connected_socket,"error",5);
  }
  
  ret = close(connected_socket);
  return 0;

}


そう。俺が書いたのは5行だけ。
しかも何なら
if(!system("kill `pidof mpg123`")) write(connected_socket,"success",7);
else write(connected_socket,"error",5);

こう書いてやりゃ2行だ。

で、この5行(ないし2行)の意味は、
とりあえずif文の条件の中で、killコマンドを発行しちゃうわけで。
たまたまkillコマンドってのは成功したら黙ってるから、結果が空っぽなら成功なんだろーなって感じで、"success"って文字列を接続してきたクライアントに送ってやる。
で、エラーだったらゴタゴタ抜かすので、そんなときは"error"って文字列を。
こんだけで事足りる。

そんで、このサーバに携帯から刺激を与えるためのPHPスクリプト。
仮にstop_mp3.phpと名付けよう。

stop_mp3.php

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<?PHP
/*************************************************************************************************
  Name:stop_mp3.php

  Action:MP3再生の目覚ましを止める

                2007.06.13 Ver.0.01 Genki wrote

  Spec.
  Ver.0.01  正しいパス送ったらボタン出る。ボタン押したらソケット開く。

***************************************************************************************************/
//各種設定
mb_internal_encoding("euc-jp");
// NOTICEエラー出さないように
// 編集・テスト動作時はコメントアウトすること。
error_reporting(E_ALL & ~E_NOTICE);

$pass = abcdef;
$port = 99999;

?>
<HTML>
<HEAD>
<meta http-equiv="Content-Type" content="text/php; charset=euc-jp">
<TITLE>
Stop mp3
</TITLE>
</HEAD>
<BODY bgcolor="#CCCCCC">
Stop mp3<BR><BR>
<?PHP
$p = $_POST['p'];
$a = $_POST['a'];
if($p == $pass){
  if($a == "yes"){
    $sock = fsockopen("localhost",$port) or print "ストップサーバ動いてない";
    $msg = fgets($sock,1024);
    if($msg == "success"){
      echo "止めた";
    }elseif($msg == "error"){
      echo "止めれなかった";
    }
  }else{
    echo <<<EOF
<FORM action="./index.php" method="post">
<INPUT type="hidden" name="p" value="$pass">
<INPUT type="hidden" name="a" value="yes">
<INPUT type="submit" value="Stop mp3">
</FORM>
EOF;
  }
}else{
  echo <<<EOF
<FORM action="./index.php" method="post">
<INPUT type="password" name="p" maxlength=12>
<INPUT type="submit" value="Login">
</FORM>
EOF;

}

echo <<<EOF
</BODY>
</HTML>
EOF;

?>

こいつの動作は、


  1. 正しいパスが送られてなかったらパスワード入力フォームを表示。
  2. パスが送られてても、a=yesが無かったらストップボタンを表示。
    (これを画面メモすれば、ボタンを押すだけで止めれるってページを作るため。)
  3. パスとa=yesが揃ったら、stop_mp3_serverのソケットを開く。

となる。
で、ソケット開いた結果帰ってきた$msgの内容によって、「止めた」「止めれんかった」のメッセージを表示。
接続エラーなら、「サーバ動いてへん」と表示。

ここで、素敵なスキルアップを果たした。

$sock = fsockopen("localhost",$port) or print "ストップサーバ動いてない";

この行、printがechoでは動かんかった。
戻り値の無いechoではor演算の対象にならず、文法エラーが出るって感じかな?
初めてprintじゃないとダメな状況に遭遇しました。

数日前に分からんっつってたことが、いきなり分かった。