Port multiplexing technology, this can be a good solution to the problem of surprise group and stream_socket_server performance bottlenecks.
<?php
/**
* Multi-process IO multiplexing libevent
* Handle multiple connections at the same time
* Port Multiplexing---recommended PHP7
*/
Class Xtgxiso_server
{
Public $socket = false;
Public $master = Array ();
public $onConnect = null;
public $onMessage = null;
public $onClose = null;
Public $process _num = 2;
Private $pids = Array ();
Public $receive = Array ();
Private $host = ' 127.0.0.1 ';
Private $port = 1215;
function __construct ($host = "0.0.0.0", $port =1215) {
To produce a child process branch
$pid = Pcntl_fork ();
if ($pid = = 1) {
Die ("Could not fork"); Pcntl_fork Return-1 indicates the creation of a child process failed
else if ($pid) {
Exit (); Pcntl_fork returns the process number of the child process created in the parent process
} else {
Pcntl_fork returned by child process 0
}
Detach from the current terminal
if (posix_setsid () = =-1) {
Die ("Could not detach from terminal");
}
Umask (0);
$this->host = $host;
$this->port = $port;
}
Private Function start_worker_process () {
$pid = Pcntl_fork ();
Switch ($pid) {
Case-1:
echo "Fork error: {$i} \ r \ n";
Exit
Case 0:
$context _option[' socket '] [' so_reuseport '] = 1;
$context = Stream_context_create ($context _option);
$this->socket = Stream_socket_server ("tcp://". $this->host. ":" $this->port, $errno, $errstr, Stream_server_ BIND | Stream_server_listen, $context);
if (! $this->socket) die ($errstr.) -". $errno);
Stream_set_blocking ($this->socket,0);
$id = (int) $this->socket;
$this->master[$id] = $this->socket;
$base = Event_base_new ();
$event = Event_new ();
Event_set ($event, $this->socket, Ev_read | Ev_persist, Array (__class__, ' ev_accept '), $base);
Event_base_set ($event, $base);
Event_add ($event);
Echo Posix_getpid (). "Start run...\n";
Event_base_loop ($base);
Default
$this->pids[$pid] = $pid;
Break
}
}
Public Function run () {
for ($i = 1; $i <= $this->process_num; $i + +) {
$this->start_worker_process ();
}
while (1) {
foreach ($this->pids as $i => $pid) {
if ($pid) {
$res = Pcntl_waitpid ($pid, $status, Wnohang);
if ($res = = 1 | | $res > 0) {
&nbs p; $this->start_worker_process ();
unset ($this->pids[$pid]);
}
}
}
Sleep (1);
}
}
Public Function ev_accept ($socket, $flag, $base) {
$connection = @stream_socket_accept ($socket);
Echo Posix_getpid (). "--accepted". Stream_socket_get_name ($connection, True). "\ n";
if (! $connection) {
Return
}
Stream_set_blocking ($connection, 0);
$id = (int) $connection;
if ($this->onconnect) {
Call_user_func ($this->onconnect, $connection);
}
$buffer = Event_buffer_new ($connection, Array (__class__, ' Ev_read '), Array (__class__, ' ev_write '), Array (__class__, ' Ev_error '), $id);
Event_buffer_base_set ($buffer, $base);
Event_buffer_timeout_set ($buffer, 30, 30);
Event_buffer_watermark_set ($buffer, Ev_read, 0, 0XFFFFFF);
Event_buffer_priority_set ($buffer, 10);
Event_buffer_enable ($buffer, Ev_read | Ev_persist);
$this->master[$id] = $connection;
$this->buffer[$id] = $buffer;
$this->receive[$id] = ';
}
function Ev_read ($buffer, $id)
{
while (1) {
$read = Event_buffer_read ($buffer, 3);
if ($read = = = ' | | $read = = FALSE)
{
Break
}
$pos = Strpos ($read, "\ n");
if ($pos = = False)
{
$this->receive[$id]. = $read;
echo "Received:". $read. "; Not all package,continue recdiveing\n ";
}else{
$this->receive[$id]. = Trim (substr ($read, 0, $pos + 1));
$read = substr ($read, $pos + 1);
if ($this->onmessage)
{
Call_user_func ($this->onmessage, $this->master[$id], $this->receive[$id]);
}
Switch ($this->receive[$id]) {
Case "Quit":
echo "Client close conn\n";
if ($this->onclose) {
Call_user_func ($this->onclose, $this->master[$id]);
}
Fclose ($this->master[$id]);
Break
Default
echo "All package:\n";
echo $this->receive[$id]. " \ n ";
Break
}
$this->receive[$id]= ';
}
}
}
function Ev_write ($buffer, $id)
{
echo "$id--". " \ n ";
}
function Ev_error ($buffer, $error, $id)
{
echo "Ev_error-". $error. " \ n ";
}
}
$server = new Xtgxiso_server ();
$server->onconnect = function ($conn) {
echo "OnConnect--accepted". Stream_socket_get_name ($conn, True). "\ n";
Fwrite ($conn, "conn success\n");
};
$server->onmessage = function ($conn, $msg) {
echo "OnMessage--". $msg. "\ n";
Fwrite ($conn, "received". $msg. " \ n ");
};
$server->onclose = function ($conn) {
echo "OnClose--". Stream_socket_get_name ($conn, True). "\ n";
};
$server->run ();
After the evolution of many service models, we have achieved a high-performance service model!