php怎么用websocket(76phpEvent库操作socket注意事项)
- 再次执行上一篇的案例
此种情况有点类似定时器,隔n秒执行一次的效果。如果要反复执行监听。需要加上"Event::PERSIST"
- 修改Event构造方法的参数
$eventsocket = new Event($eventBase,$resource,Event::READ|Event::PERSIST,'accept');
- 再次执行
2、嵌套问题
这里嵌套是指在回调方法里面,新增加"监听"。比如之前案例中,在回调方法"accept",新增加可读or可写的监听
2.1、问题案例
在接收到新的socket链接时,针对该socket链接,监听其read操作
- 源码
<?php
/**
* Copyright (C) Iamasb
* @project : 3、workerman相关知识点
* @explain : Event操作socket注意事项
* @filename : 40、Event操作socket注意事项.php
* @author : xiaobei 2801616735@qq.com
*/
// 创建tcp
if (!($resource = socket_create(AF_INET,SOCK_STREAM,SOL_TCP))) {
echo "socket create is error";
exit();
}
// 设置端口复用
if (!socket_set_option($resource, SOL_SOCKET, SO_REUSEADDR, 1)) {
echo 'Unable to set option on socket: '. socket_strerror(socket_last_error()) . PHP_EOL;
exit;
}
// 绑定当前主机和端口
if (!socket_bind($resource,'0.0.0.0','1234')) {
echo "socket bind is error";
exit();
}
// 启动监听
if (!socket_listen($resource)) {
echo "socket listen is error";
exit();
}
$eventBase = new EventBase();
$eventSocket = new Event($eventBase,$resource,Event::READ,'accept');
$eventSocket->add();
$eventBase->loop();
function accept($socket)
{
global $eventBase;
$client = socket_accept($socket);
socket_getpeername($client,$address,$port);
echo "new client->",$address,':',$port,PHP_EOL;
// 对新连接进行监听"read"
$eventSocket = new Event($eventBase,$client,Event::READ|Event::PERSIST,'read',$client);
if (!$eventSocket || !$eventSocket->add()) {
echo "error",PHP_EOL;
}
}
function read($socket)
{
$string = socket_read($socket,1024);
echo "receive from client->",trim($string),PHP_EOL;
socket_close($socket);
}
- 执行结果
- 结果分析
首先是设置read监听不起作用,其次是整个服务都挂掉了。为什么?
答: 从accept函数中得知,新创建了一个event实例化对象,然后加入监听中。但是但离开accept函数后,根据变量的作用域,就被系统收回了。因此不起作用
2.2、修改方案
通过引入全局变量,保存变量。从而延长变量的生命周期
- 修改后的源码
<?php
/**
* Copyright (C) Iamasb
* @project : 3、workerman相关知识点
* @explain : Event操作socket
* @filename : 39、Event操作socket.php
* @author : xiaobei 2801616735@qq.com
*/
// 创建tcp
if (!($resource = socket_create(AF_INET,SOCK_STREAM,SOL_TCP))) {
echo "socket create is error";
exit();
}
// 设置端口复用
if (!socket_set_option($resource, SOL_SOCKET, SO_REUSEADDR, 1)) {
echo 'Unable to set option on socket: '. socket_strerror(socket_last_error()) . PHP_EOL;
exit;
}
// 绑定当前主机和端口
if (!socket_bind($resource,'0.0.0.0','1234')) {
echo "socket bind is error";
exit();
}
// 启动监听
if (!socket_listen($resource)) {
echo "socket listen is error";
exit();
}
$GLOBALS['event'] = array();
$GLOBALS['eventBase'] = new EventBase();
$eventSocket = new Event($eventBase,$resource,Event::READ|Event::PERSIST,'accept');
$eventSocket->add();
$GLOBALS['event'][(int)$resource] = $eventSocket;
$eventBase->loop();
function accept($socket)
{
echo "accept->",PHP_EOL;
$client = socket_accept($socket);
socket_getpeername($client,$address,$port);
echo "new client->",$address,':',$port,PHP_EOL;
$eventSocket = new Event($GLOBALS['eventBase'],$client,Event::READ|Event::PERSIST,'read',$client);
if (!$eventSocket || !$eventSocket->add()) {
echo "error",PHP_EOL;
}
$GLOBALS['event'][(int)$client] = $eventSocket;
return true;
}
function read($socket)
{
$string = socket_read($socket,1024);
echo "receive from client->",trim($string),PHP_EOL;
$eventSocket = new Event($GLOBALS['eventBase'],$socket,Event::WRITE|Event::PERSIST,'write',$socket);
if (!$eventSocket || !$eventSocket->add()) {
echo "error",PHP_EOL;
}
$GLOBALS['event'][(int)$socket] = $eventSocket;
}
function write($socket)
{
echo "todo->Write",PHP_EOL;
$string = "hello\n";
socket_write($socket,$string,strlen($string));
socket_close($socket);
$GLOBALS['event'][(int)$socket]->del();
unset($GLOBALS['event'][(int)$socket]);
}
- 执行结果
,
免责声明:本文仅代表文章作者的个人观点,与本站无关。其原创性、真实性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容文字的真实性、完整性和原创性本站不作任何保证或承诺,请读者仅作参考,并自行核实相关内容。文章投诉邮箱:anhduc.ph@yahoo.com