发布于2026-07-07 阅读(0)
扫一扫,手机访问
先看两个很容易搞混的函数:swoole_event_add和swoole_event_set。它们都是用来向Swoole事件循环注册或调整文件描述符(fd)监听行为的,语义上完全不同——如果混着用,很可能碰到回调不执行、事件丢失,甚至就给你返回一个false,你都不知道是怎么回事。

那么,要怎么区分它们?
swoole_event_add,才能调swoole_event_set很多人容易犯一个错:认为swoole_event_set也可以独立注册一个fd。实际上它只对已经在Reactor里存在的fd有作用。换句话说,这个fd要是从来没有swoole_event_add进去过,set就直接返回false,而且没有任何异常提示。这一点最坑。
swoole_event_set($fd, $cb, null, SWOOLE_EVENT_READ),结果返回了false,还以为是参数填错了,其实是忘了先add。swoole_event_exist($fd)检查一下。如果是v4.7或更早的版本,那就只能靠自己维护一个fd状态映射表了。fopen或者stream_socket_client创建的资源,也必须显式地swoole_event_add,它才会真正进入事件循环的流程。swoole_event_add是初始化,swoole_event_set是动态调整从实际运行表现来看,swoole_event_add干的是三件事:把fd注册进epoll或kqueue、设置初始回调、启用指定事件掩码。而swoole_event_set只处理两件事:替换回调函数(前提是传了非null的值),以及开关事件监听(靠$flags参数控制)。
swoole_event_add中的$write_callback和$event_flag是必填逻辑的一部分;而swoole_event_set里如果对应参数传了null,意思是不修改,而不是清空。swoole_event_add监听可读状态,等reap_async_query结束了,再用swoole_event_set($fd, null, null, SWOOLE_EVENT_WRITE)把监听模式切到可写,为下一次查询做准备。swoole_event_set($fd, null, null, SWOOLE_EVENT_READ)并不会清除原有的回调,它只是把可写关了、把可读打开了——之前的read_callback依然有效。swoole_event_set释放不管你给$read_callback或$write_callback传多少次null,只要没用swoole_event_del,PHP层回调的zval就会一直被引用着,内存不会释放。闭包捕获的那些变量也会一直活着。
swoole_event_set替换回调但不del,内存会一点一点涨上去,时间长了很可能是问题。swoole_event_del($fd)来配对清理。swoole_event_del会把读/写回调一次全释放,同时把fd从Reactor里移除,不会管你之前调了多少次set。最后,最容易忽略的一点:事件掩码($flags)和回调函数是解耦的。你可以只改掩码不改回调,也可以只改回调不改掩码。但是,一旦掩码里没有SWOOLE_EVENT_READ,却设了$read_callback,这个回调永远不会被执行——Swoole底层只按掩码投递事件,不会校验回调是否存在。
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8