多路复用解决了:减少了用户态内核态的无用切换。
多路复用器:只能告诉你哪些可以读取,然后,你要自己读取,只要程序自己读取,同步模型。NIO/Epoll就是同步读取。
关于同步/异步分别可对应:IO和计算,如同步IO/异步IO/同步计算/异步计算。
对于来1万个连接:如果用while(1)时,则是10000次read,如果没有数据read系统调用会返回-1,复杂度是10000,
用select呢,场景如果有3个,则于是出现select O(1)一次,再加上另外三个的read有仨个,于是复杂度是4,远远小于10000。
异步IO:IOCP (内核级维护线程,IO读取处理。)
只要内核通知,自己去读取,也就是NIO,同步IO。
如果内核有数据直接给你,你不用去做了,就是异步IO。
注意多路复用!= 多线程,流传网络的PHP 模拟多线程(如Thread类等)对PHP网络通信级的处理没有一点意义,而网络的不阻塞通信应采用PHP 的socket_select多路复用,类似于java nio
多路复用器:只能告诉你哪些可以读取,然后,你要自己读取,只要程序自己读取,同步模型。NIO/Epoll就是同步读取。
关于同步/异步分别可对应:IO和计算,如同步IO/异步IO/同步计算/异步计算。
对于来1万个连接:如果用while(1)时,则是10000次read,如果没有数据read系统调用会返回-1,复杂度是10000,
用select呢,场景如果有3个,则于是出现select O(1)一次,再加上另外三个的read有仨个,于是复杂度是4,远远小于10000。
异步IO:IOCP (内核级维护线程,IO读取处理。)
只要内核通知,自己去读取,也就是NIO,同步IO。
如果内核有数据直接给你,你不用去做了,就是异步IO。
注意多路复用!= 多线程,流传网络的PHP 模拟多线程(如Thread类等)对PHP网络通信级的处理没有一点意义,而网络的不阻塞通信应采用PHP 的socket_select多路复用,类似于java nio
<?php
error_reporting(E_ALL);
set_time_limit(0);
ini_set("allow_call_time_pass_reference",true);
//监听端口
$PORT = 8888;
//最大连接池
$MAX_USERS = 50;
//创建监听端口
$sock = socket_create_listen($PORT);
if (!$sock)
{
exit(1);
}
//不阻塞
socket_set_nonblock($sock);
$connections = array();
$input = array();
$close = array();
while (true)
{
$readfds = array_merge($connections, array($sock));
$writefds = array();
//选择一个连接,获取读、写连接通道
if (socket_select($readfds, $writefds, $e = null, $t=60))
{
foreach ($readfds as $rfd)
{
//如果是当前服务端的监听连接
if ($rfd == $sock)
{
//接受客户端连接
$newconn = socket_accept($sock);
$i = (int)$newconn;
$reject = '';
if (count($connections) >= $MAX_USERS)
{
$reject = "Server full. Try again later.\n";
}
//将当前客户端连接放如socket_select选择
$connections[$i] = $newconn;
//输入的连接资源缓存容器
$writefds[$i] = $newconn;
//连接不正常
if ($reject)
{
$close[$i] = true;
}
else
{
echo "Welcome to the PHP Chat Server!\n";
}
//初始化当前连接读取内容的缓存容器
$input[$i] = "";
continue;
}
//客户端连接
$i = (int)$rfd;
//读取
$tmp = @socket_read($rfd, 2048, PHP_NORMAL_READ);
if (!$tmp)
{
//读取不到内容
print "connection closed on socket $i\n";
close($i);
continue;
}
$input[$i] .= $tmp;
$tmp = substr($input[$i], -1);
if ($tmp != "\r" && $tmp != "\n")
{
// no end of line, more data coming
continue;
}
$line = trim($input[$i]);
$input[$i] = "";
echo 'Client >>'.$line.'\n';
}
foreach ($writefds as $wfd)
{
$i = (int)$wfd;
$w = socket_write($wfd, "hello");
}
}
}
function close($i)
{
global $connections, $input, $close;
socket_shutdown($connections[$i]);
socket_close($connections[$i]);
unset($connections[$i]);
unset($input[$i]);
unset($close[$i]);
}
?>
error_reporting(E_ALL);
set_time_limit(0);
ini_set("allow_call_time_pass_reference",true);
//监听端口
$PORT = 8888;
//最大连接池
$MAX_USERS = 50;
//创建监听端口
$sock = socket_create_listen($PORT);
if (!$sock)
{
exit(1);
}
//不阻塞
socket_set_nonblock($sock);
$connections = array();
$input = array();
$close = array();
while (true)
{
$readfds = array_merge($connections, array($sock));
$writefds = array();
//选择一个连接,获取读、写连接通道
if (socket_select($readfds, $writefds, $e = null, $t=60))
{
foreach ($readfds as $rfd)
{
//如果是当前服务端的监听连接
if ($rfd == $sock)
{
//接受客户端连接
$newconn = socket_accept($sock);
$i = (int)$newconn;
$reject = '';
if (count($connections) >= $MAX_USERS)
{
$reject = "Server full. Try again later.\n";
}
//将当前客户端连接放如socket_select选择
$connections[$i] = $newconn;
//输入的连接资源缓存容器
$writefds[$i] = $newconn;
//连接不正常
if ($reject)
{
$close[$i] = true;
}
else
{
echo "Welcome to the PHP Chat Server!\n";
}
//初始化当前连接读取内容的缓存容器
$input[$i] = "";
continue;
}
//客户端连接
$i = (int)$rfd;
//读取
$tmp = @socket_read($rfd, 2048, PHP_NORMAL_READ);
if (!$tmp)
{
//读取不到内容
print "connection closed on socket $i\n";
close($i);
continue;
}
$input[$i] .= $tmp;
$tmp = substr($input[$i], -1);
if ($tmp != "\r" && $tmp != "\n")
{
// no end of line, more data coming
continue;
}
$line = trim($input[$i]);
$input[$i] = "";
echo 'Client >>'.$line.'\n';
}
foreach ($writefds as $wfd)
{
$i = (int)$wfd;
$w = socket_write($wfd, "hello");
}
}
}
function close($i)
{
global $connections, $input, $close;
socket_shutdown($connections[$i]);
socket_close($connections[$i]);
unset($connections[$i]);
unset($input[$i]);
unset($close[$i]);
}
?>
作者:jackxiang@向东博客 专注WEB应用 构架之美 --- 构架之美,在于尽态极妍 | 应用之美,在于药到病除
地址:https://jackxiang.com/post/3410/
版权所有。转载时必须以链接形式注明作者和原始出处及本声明!
最后编辑: jackxiang 编辑于2020-5-4 21:37
评论列表