class socket { private $_socket; private $_domain = AF_INET; private $_type = SOCK_STREAM; private $_protocol = SOL_TCP; private $_clients = []; private $_max_clients = 10; public function __construct() { if (!extension_loaded('sockets')) { die('the sockets extension is not loaded!'); } if (($this->_socket = $this->create($this->_domain, $this->_type, $this->_protocol)) < 0) { $this->error($this->_socket); } } public function start($ip, $port) { if (($res = $this->set_option()) < 0) { $this->error($res); } if (($res = $this->bind($ip, $port)) < 0) { $this->error($res); } if (($res = $this->listen(5)) < 0) { $this->error($res); } #使用非阻塞模式 socket_set_nonblock($this->_socket); echo "listen on port " . $port . "..." . PHP_EOL; $clients = array($this->_socket); while (true) { $this->_clients = $clients; $write = []; $except = []; if (socket_select($this->_clients, $write, $except, 0) < 1) { continue; } if (in_array($this->_socket, $this->_clients)) { $clients[] = $connection = $this->connect(); // if (($clients + 1) > $this->_max_clients) { // echo "Too many clients..." . PHP_EOL; // } else { $this->send($connection, "welcome!\nthere are " . (count($clients) - 1) . " client here\n"); socket_getpeername($connection, $client_ip); echo "new client connected:$client_ip\n"; $key = array_search($connection, $this->_clients); unset($this->_clients[$key]); // } } foreach($this->_clients as $client){ $receive = $this->receive($client); if($receive===false){ $key=array_search($client, $clients); unset($clients[$key]); echo "client disconnected.\n"; continue; } $receive = trim($receive); if(!empty($receive)){ foreach($clients as $send_socket){ if($send_socket==$this->_socket||$send_socket==$client){ continue; } $this->send($send_socket, $this->_socket .">".$client.">"."$receive\n"); } } } } $this->close(); } public function bind($ip, $port) { socket_bind($this->_socket, $ip, $port); } public function listen($max_clients) { socket_listen($this->_socket, $max_clients); } public function connect() { return socket_accept($this->_socket); } public function send($connection, $msg) { socket_write($connection, $msg); } public function receive($client) { return socket_read($client, 819292, PHP_NORMAL_READ); } public function error($resource) { echo socket_strerror($resource) . PHP_EOL; } public function close() { socket_close($this->_socket); } public function create($domain = AF_INET, $type = SOCK_STREAM, $protocol = SOL_TCP) { return socket_create($domain, $type, $protocol); } public function set_option(){ socket_set_option($this->_socket,SOL_SOCKET,SO_REUSEADDR,1); } }
demo
ini_set("display_errors", 1); include_once INC_PATH . "class/socket.class.php"; $socket = new socket(); $socket->start("192.168.2.113", 1371);