Socketでechoサーバ,クライアント

Socketを使つかってみるためのメモ

とりあえずechoサーバ書くよね

  • 複数のコネクションを受け付けるechoサーバ
  • メッセージは他の接続者には送信しない(サーバとクライアントの1対1)
  • "quit"を受けると接続を終了
  • "shutdown"を受け取るとサーバを終了

サーバはこんな感じ

<?php
error_reporting(E_ALL);

//Allow  the script to hang
set_time_limit(0);

//enables flush
ob_implicit_flush();

$address = '192.168.0.1'; //addr
$port = 10000; //port
$backlog = 5;
$bufsize = 2048;

//socket:create→bind→listen
if (($sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) === false){
    echo "socket_create() failed: reason: " . socket_strerror(socket_last_error()) . "\n";
}

if (socket_bind($sock, $address, $port) === false){
    echo "socket_bind() failed: reason: " . socket_strerror(socket_last_error($sock)) . "\n";
}

if (socket_listen($sock, $backlog) === false){
    echo "socket_listen() failed: reason: " . socket_strerror(socket_last_error($sock)) . "\n";
}

//nonblockmode
if(socket_set_nonblock($sock) === false){
  echo "socket_set_nonblock() failed: reason: ". socket_strerror(socket_last_error($sock)). "\n";
}

//clients list
$clients = array($sock);

//for select
$read_sockets = array();
$write_sockets = NULL;
$error_sockets = NULL;
$select_interval = 0; //second

while(true){
 
  $read_sockets = $clients;

  //read only
  $select = socket_select($read_sockets, $write_sockets,
			  $error_sockets, $select_interval);
  
  //new client or new message
  if($select >= 1){
    
    //new client
    if(in_array($sock, $read_sockets)){
      
      //add client
      $clients[] = $newsock = socket_accept($sock);
      
      //delete new client from read list
      $clients_key = array_search ($sock, $read_sockets);
      unset($read_sockets[$clients_key]);      
      
    }

    //read message
    foreach($read_sockets as $read_key => $read_socket){

      //reaf failed
      if(($read_buf = socket_read($read_socket, $bufsize, PHP_NORMAL_READ)) === false){

	echo "socket_read() failed: reason: " . socket_strerror(socket_last_error($read_socket)) . "\n";

    //delete client
	$clients_key = array_search($read_socket, $clients);
	unset($read_sockets[$read_key]);
	unset($clients[$clients_key]);

      }

      //invalied message
      else if (!$read_buf = trim($read_buf)){

        //delete client
	$clients_key = array_search($read_socket, $clients);
	unset($read_sockets[$read_key]);
	unset($clients[$clients_key]);
	
        continue;

      }

      echo $read_buf."\n";
      
      //end of connection 
      if ($read_buf == 'quit'){

	$clients_key = array_search($read_socket, $clients);
	unset($read_sockets[$read_key]);
	unset($clients[$clients_key]);

      }

      //shutdown server
      else if ($read_buf == 'shutdown'){

        //delete all client
	foreach($clients as $clients_key => $client){ 

	  if($sock != $client){
	    unset($client);
	  }

	}
	break 2;

      }

      //echo back
      else{ 

        //write message
	$write_buf = $read_buf."\n";
	if(socket_write($read_socket, $write_buf, strlen($write_buf)) === false){

	  echo "socket_write() failed: rason: " . socket_strerror(socket_last_error($read_sock));

	  $clients_key = array_search($read_socket, $clients);
	  unset($read_sockets[$read_key]);
	  unset($clients[$clients_key]);

	}
      }
    }
  }

  //There is no readable socket
  else if($select == 0){
    continue;
  }
  
  //select error
  else if($select === false){

    echo "socket_select() failed: reason: ". sockets_strerror(socket_last_error($read_sock)) . "\n";

    break;
  }
  
}

//close socket
socket_close($sock);

?>

クライアントはこちら

<?php

$test_servaddr = '192.168.0.1'; //server address
$test_servport = 10000; //port

//socket:create→connect
if(($test_sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) === false){ 
  echo "socket_create() error:". socket_strerror(socket_last_error());
}

if((socket_connect($test_sock, $test_servaddr, $test_servport)) === false){
  echo "socket_connect() error:".socket_strerror(socket_last_error());
}


while($test_inputbuf = fgets(STDIN,2048)){

  if(!($test_inputbuf = trim($test_inputbuf))){
    continue;
  }

  //output and create message
  echo "write:".$test_inputbuf."\n";
  $test_writebuf = $test_inputbuf."\n";

  //write message
  if(socket_write($test_sock, $test_writebuf, strlen($test_writebuf)) === false){
    echo "socket_write()  error:".socket_strerror(socket_last_error());
  }

  //end of connection
  switch($test_inputbuf) {

  case 'quit':
    socket_close($test_sock);
    break 2;

  case 'shutdown':
    socket_close($test_sock);
    break 2;

  default :
    break;

  }

  //read and output message
  if(($test_readbuf = socket_read($test_sock, 2048, PHP_NORMAL_READ)) === false){
    echo "socket_read() error:". socket_strerror(socket_last_error());
  }
  else{
    echo "read:".$test_readbuf;
  }

}

?>


Cとかとほとんど変わりません。