PHPでソケット通信(UDP)
今回、PHPでソケット通信を行いました。
環境としては、C言語でクライアント側(UDPを送る)を行い、PHPでサーバ側を行うというものでした。今回C言語のクライアント側は元々あるものとし、PHP側のサーバを作成しました。作成したPHPのコードを以下に示します。
<?php class packet_format{ public $type; public $message; public $recv_date; } $recv_data = new packet_format; $port = 5050; //UDPのソケット作成 $sock = socket_create(AF_INET,SOCK_DGRAM,SOL_UDP); socket_bind($sock,'127.0.0.1',$port); $from = ''; while(true){ //UDPのソケットを受信 socket_recvfrom($sock,$buf,4096,0,$from,$port); //バイナリで取得しているため、unpackでデータを取得 $packet_data = unpack("Stype/Smessage/ITimestamp",$buf); //対応する変数に代入 $recv_data->type = $array["type"]; $recv_data->message = $array["message"]; $recv_data->recv_date = date('D M d H:i:s Y',$array["Timestamp"]); /* 確認応答パケットをUDPで送信(データは1,2,3,4) 送るデータをpackでバイナリ文字列にパックした後送る */ $socket = socket_create(AF_INET,SOCK_DGRAM,SOL_UDP); $sock_data = pack('SSSS',1,2,3,4); socket_sendto($socket,$sock_data,strlen($sock_data),0,$from,$port); } //close socket socket_close($sock); socket_close($socket); ?>
今回の場合はサーバを作成しているため、while文で常に起動させておきます。
UDPのソケットの受信の順序
- socket_create関数で受信ソケットの作成
- socket_bind関数でソケットに名前を付ける
- socket_recvfrom関数でソケットの受信待ち
- unpack関数でソケットのバイナリデータを解析
- socket_close関数でソケットを閉じる
UDPの場合はソケットを作成する際に、socket_create関数の第2,3引数には、SOCK_DGRAMとSOL_UDPを指定する。TCPでは、SOCK_DGRAM→SOCK_STREAMで、SOL_UDP→SOL_TCPで行けると思います。
次に、bindでソケットに名前を付けた後、socket_recvfromでパケットの受信を行います。受信後の引数である$fromと$portには、ソケットの送信者のIPアドレスとポート番号の情報が入るみたいです。
次に、受信したバイナリデータ(ソケットからのデータ)をそのままデータとして取得はできませんので、unpack関数を利用し、それぞれのデータとして分解します。戻り値としては、配列として返却します。
unpack関数では、
<?php unpack("Stype",$buf); //array("type"=>Sのデータ); ?>
のように使うのですが、Sは、データのフォーマットでありtypeは、連想配列のkeyの名前となります。
<?php unpack("S",$buf); //array("1"=>Sのデータ); ?>
でも良いのですが、この場合では、配列の添え字が1から始まります。
データのフォーマットについては、送信の際にpack関数を用いるのですが、その時に指定したフォーマットを同様にunpackで指定するとよいと思います。
PHP: pack - Manual
ここにデータのフォーマットが書かれています。
そして、最後はsocket_closeでソケットを閉じておしまいです。