我的编程空间,编程开发者的网络收藏夹
学习永远不晚

PHP+Socket中IO多路复用及实现web服务器的方法是什么

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

PHP+Socket中IO多路复用及实现web服务器的方法是什么

本篇内容介绍了“PHP+Socket中IO多路复用及实现web服务器的方法是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

php原生socket之IO多路复用以及实现web服务器

多路复用

前文 通过原生 socket 实现了简单的服务端与客户端通信,但当有多个客户端连接时,服务端仅能处理第一个客户端的请求,而无法对后续客户端服务

PHP+Socket中IO多路复用及实现web服务器的方法是什么

产生这种情况的原因是因为IO模型是阻塞的,同一时刻只能由一个客户端进行访问,解决此问题主要有两种解决方案:

  • 多进程,即在服务端启动多个进程监听

  • IO多路复用机制,简单来说实现了 N 个客户端使用一根网线同时访问

同时多路复用又分为两个不同的模型,即 selectepoll,常见的软件中,Apache 使用了 select 模型,nginx 则使用 epoll 模型。在 php 中内置了 select 模型,对应的函数为 socket_select,多路复用是实现 http 服务器的基础

语法

在前文中我们介绍了 php 原生 socket 内置了 socket_select 函数实现了 select 模型,其语法如下:

socket_select(    array &$read,    array &$write,    array &$except,    int $seconds [,    int $microseconds = 0]): int|false

参数
  • read

    服务端监听的套接字资源,当他有变化(即收到新的消息或有客户端连接、断开)时,socket_select 函数才会返回(否则继续阻塞),同时修改该变量为当前发生事件(收到消息或有客户端连接、断开)的套接字资源列表,并继续向下执行。

  • write

    监听是否有客户端写数据,传入 null 则代表不关心是否有写变化

  • except

    套接字内要排除的元素,传入 null 是 「监听」 全部

  • seconds

    秒和微秒一起构成超时参数。如果传入 null 则会阻塞,为 0 非阻塞,如果是 >0 则为最大阻塞时间

  • microseconds

优化

我们在 上篇文章 简单实现了 socket 服务端监听与客户端的连接,接下来我们在服务端监听代码的基础上通过多路复用优化代码:

<?php// 创建套接字$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);// 设置 ip 被释放后立即可使用socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, true);// 绑定ip与端口socket_bind($socket, 0, 8888);// 开始监听socket_listen($socket);$sockets[] = $socket;while (true) {    $tmp_sockets = $sockets;    socket_select($tmp_sockets, $write, $except, null);    foreach ($tmp_sockets as $sock) {        // 如果当前套接字等于 socket_create 创建的套接字,说明是有新的连接或有新的断开连接        if ($sock == $socket) {            $conn_sock = socket_accept($socket);            $sockets[] = $conn_sock;            socket_getpeername($conn_sock, $ip, $port);            echo '请求ip: ' . $ip . '端口: ' . $port . PHP_EOL;        } else { // 否则说明是之前连接的客户端发来消息            $msg = socket_read($sock, 10240);            socket_write($sock, strtoupper($msg));            echo $msg;        }    }}

在本示例中 socket_select 函数会阻塞当前进程,当 $tmp_sockets 数组内的 socket 资源有新的客户端连接或断开或收到新消息时,会将 $tmp_sockets 数组修改为当前活跃的 socket 资源,随后通过遍历该数组处理业务逻辑。

PHP+Socket中IO多路复用及实现web服务器的方法是什么

使用socket实现简易http服务器

http 协议是在 socket 的基础上规定了指定的数据格式,所以我们只需在 socket_write 时按照格式发送数据,浏览器就可正常响应请求

<?php// 创建套接字$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);// 设置 ip 被释放后立即可使用socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, true);// 绑定ip与端口socket_bind($socket, 0, 8888);// 开始监听socket_listen($socket);$sockets[] = $socket;while (true) {    $tmp_sockets = $sockets;    socket_select($tmp_sockets, $write, $except, null);    foreach ($tmp_sockets as $sock) {        if ($sock == $socket) {            $conn_sock = socket_accept($socket);            $sockets[] = $conn_sock;        } else {            $msg = socket_read($sock, 10240);            var_dump($msg);            if ($msg == '') return;            $output = '<h2>this is php worker</h2>';            $len = strlen($output);            $response = "HTTP/1.1 200 OK\r\n";            $response .= "content-type: text/html\r\n";            $response .= "server: php socket\r\n";            $response .= "Content-Length: {$len}\r\n\r\n";            $response .= $output;            socket_write($sock, $response);        }    }}

在服务端运行此示例,随后在浏览器访问 ip:8888 ,可以看到如下:

PHP+Socket中IO多路复用及实现web服务器的方法是什么

同时服务端会输出如下内容:

GET / HTTP/1.1Host: 124.222.**.**:8888Connection: keep-aliveCache-Control: max-age=0Upgrade-Insecure-Requests: 1User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.0.0 Safari/537.36Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9Accept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9Cookie: jenkins-timestamper-offset=-28800000; _ga=GA1.1.1403944751.1652010033; _ga_2GM6102E19=GS1.1.1652802985.7.1.1652803014.0

该内容即为用户端请求原始数据,可解析此数据并根据请求做出响应,比如使用 file_get_content 读取指定文件内容返回给浏览器。

“PHP+Socket中IO多路复用及实现web服务器的方法是什么”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注编程网网站,小编将为大家输出更多高质量的实用文章!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

PHP+Socket中IO多路复用及实现web服务器的方法是什么

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

PHP+Socket中IO多路复用及实现web服务器的方法是什么

本篇内容介绍了“PHP+Socket中IO多路复用及实现web服务器的方法是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!php原生so
2023-07-05

服务器租用实现负载均衡的方法是什么

实现负载均衡的方法有很多种,以下是一些常见的方法:软件负载均衡器:使用软件负载均衡器如Nginx、HAProxy等,通过配置负载均衡算法和策略,将请求分发给多台服务器。硬件负载均衡器:使用专门的硬件设备如F5、Citrix等进行负载均衡,这
服务器租用实现负载均衡的方法是什么
2024-04-24

在Netdata中实现跨多个服务器和服务的聚合监控数据视图的方法是什么

在Netdata中实现跨多个服务器和服务的聚合监控数据视图的方法是通过使用Netdata的分布式架构和数据收集器。 Netdata提供了一个称为Netdata Cloud的中央管理平台,可用于集中管理和监控多个Netdata节点。要实现跨
在Netdata中实现跨多个服务器和服务的聚合监控数据视图的方法是什么
2024-06-03

编程热搜

目录