swoole_client源码解析之绑定回调函数

版权声明:转载请注明来源 https://blog.csdn.net/u013702678/article/details/82891113

看swoole_client的demo,其支持回调函数,也就是PHP业务侧设置了相应的回调函数,在达到回调函数的条件时,会触发相应的回调,目前swoole_client支持的回调函数有connect,receive等,swoole_client里设置回调函数是通过on函数实现,这篇文章我们分析下其回调函数的实现。

static PHP_METHOD(swoole_client, on)
{
    char *cb_name;
    zend_size_t cb_name_len;
    zval *zcallback;

    //解析输入参数信息,解析的参数有回调函数名,函数名长度,函数实现等。
    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &cb_name, &cb_name_len, &zcallback) == FAILURE)
    {
        return;
    }
    //读取swoole_client的type属性信息
    zval *ztype = sw_zend_read_property(swoole_client_class_entry_ptr, getThis(), SW_STRL("type")-1, 0 TSRMLS_CC);
    if (ztype == NULL || ZVAL_IS_NULL(ztype))
    {
        swoole_php_fatal_error(E_ERROR, "get swoole_client->type failed.");
        return;
    }

    if (!(Z_LVAL_P(ztype) & SW_FLAG_ASYNC))//判断是否是异步模式,异步模式不允许设置回调函数
    {
        swoole_php_fatal_error(E_ERROR, "can't register event callback functions in SYNC mode.");
        return;
    }
    //读取swoole_client的回调函数信息
    client_callback *cb = (client_callback *) swoole_get_property(getThis(), client_property_callback);
    if (!cb)//如果为空
    {
        cb = (client_callback *) emalloc(sizeof(client_callback));//申请回调函数结构空间
        bzero(cb, sizeof(client_callback));//空间初始化
        swoole_set_property(getThis(), client_property_callback, cb);//设置swoole_client的属性信息
    }

#ifdef PHP_SWOOLE_ENABLE_FASTCALL
    char *func_name = NULL;
    zend_fcall_info_cache func_cache;
    if (!sw_zend_is_callable_ex(zcallback, NULL, 0, &func_name, NULL, &func_cache, NULL TSRMLS_CC))//检查输入信息是否是可以执行的,这里通过php底层方法直接判断
    {
        swoole_php_fatal_error(E_ERROR, "Function '%s' is not callable", func_name);
        efree(func_name);
        return;
    }
    efree(func_name);
#elif defined(PHP_SWOOLE_CHECK_CALLBACK)
    char *func_name = NULL;
    if (!sw_zend_is_callable(zcallback, 0, &func_name TSRMLS_CC))
    {
        swoole_php_fatal_error(E_ERROR, "Function '%s' is not callable", func_name);
        efree(func_name);
        return;
    }
    efree(func_name);
#endif

    if (strncasecmp("connect", cb_name, cb_name_len) == 0)//绑定connect回调函数,绑定到swoole_client对应的内部对象时,就变成了onConnect函数。
    {
        zend_update_property(swoole_client_class_entry_ptr, getThis(), ZEND_STRL("onConnect"), zcallback TSRMLS_CC);
        cb->onConnect = sw_zend_read_property(swoole_client_class_entry_ptr,  getThis(), ZEND_STRL("onConnect"), 0 TSRMLS_CC);
        sw_copy_to_stack(cb->onConnect, cb->_onConnect);
#ifdef PHP_SWOOLE_ENABLE_FASTCALL
        cb->cache_onConnect = func_cache;
#endif
    }
    else if (strncasecmp("receive", cb_name, cb_name_len) == 0)//绑定receive回调函数,绑定到swoole_client对应的内部对象时,就变成了onReceive函数。
    {
        zend_update_property(swoole_client_class_entry_ptr, getThis(), ZEND_STRL("onReceive"), zcallback TSRMLS_CC);
        cb->onReceive = sw_zend_read_property(swoole_client_class_entry_ptr,  getThis(), ZEND_STRL("onReceive"), 0 TSRMLS_CC);
        sw_copy_to_stack(cb->onReceive, cb->_onReceive);
#ifdef PHP_SWOOLE_ENABLE_FASTCALL
        cb->cache_onReceive = func_cache;
#endif
    }
    else if (strncasecmp("close", cb_name, cb_name_len) == 0)//绑定close回调函数,绑定到swoole_client对应的内部对象时,就变成了onClose函数。
    {
        zend_update_property(swoole_client_class_entry_ptr, getThis(), ZEND_STRL("onClose"), zcallback TSRMLS_CC);
        cb->onClose = sw_zend_read_property(swoole_client_class_entry_ptr,  getThis(), ZEND_STRL("onClose"), 0 TSRMLS_CC);
        sw_copy_to_stack(cb->onClose, cb->_onClose);
#ifdef PHP_SWOOLE_ENABLE_FASTCALL
        cb->cache_onClose = func_cache;
#endif
    }
    else if (strncasecmp("error", cb_name, cb_name_len) == 0)//绑定error回调函数,绑定到swoole_client对应的内部对象时,就变成了onError函数。
    {
        zend_update_property(swoole_client_class_entry_ptr, getThis(), ZEND_STRL("onError"), zcallback TSRMLS_CC);
        cb->onError = sw_zend_read_property(swoole_client_class_entry_ptr,  getThis(), ZEND_STRL("onError"), 0 TSRMLS_CC);
        sw_copy_to_stack(cb->onError, cb->_onError);
#ifdef PHP_SWOOLE_ENABLE_FASTCALL
        cb->cache_onError = func_cache;
#endif
    }
    else if (strncasecmp("bufferFull", cb_name, cb_name_len) == 0)//绑定bufferFull回调函数,绑定到swoole_client对应的内部对象时,就变成了onBufferFull函数。
    {
        zend_update_property(swoole_client_class_entry_ptr, getThis(), ZEND_STRL("onBufferFull"), zcallback TSRMLS_CC);
        cb->onBufferFull = sw_zend_read_property(swoole_client_class_entry_ptr,  getThis(), ZEND_STRL("onBufferFull"), 0 TSRMLS_CC);
        sw_copy_to_stack(cb->onBufferFull, cb->_onBufferFull);
#ifdef PHP_SWOOLE_ENABLE_FASTCALL
        cb->cache_onBufferFull = func_cache;
#endif
    }
    else if (strncasecmp("bufferEmpty", cb_name, cb_name_len) == 0)//绑定bufferEmpty回调函数,绑定到swoole_client对应的内部对象时,就变成了onBufferEmpty函数。
    {
        zend_update_property(swoole_client_class_entry_ptr, getThis(), ZEND_STRL("onBufferEmpty"), zcallback TSRMLS_CC);
        cb->onBufferEmpty = sw_zend_read_property(swoole_client_class_entry_ptr,  getThis(), ZEND_STRL("onBufferEmpty"), 0 TSRMLS_CC);
        sw_copy_to_stack(cb->onBufferEmpty, cb->_onBufferEmpty);
#ifdef PHP_SWOOLE_ENABLE_FASTCALL
        cb->cache_onBufferEmpty = func_cache;
#endif
    }
    else
    {
        swoole_php_fatal_error(E_WARNING, "Unknown event callback type name '%s'.", cb_name);
        RETURN_FALSE;
    }
    RETURN_TRUE;
}

上面我们分析了绑定的逻辑,我们下面看其中回调函数的执行逻辑。

static sw_inline void execute_onConnect(swClient *cli)
{
    if (cli->timer)
    {
        swTimer_del(&SwooleG.timer, cli->timer);
        cli->timer = NULL;
    }
    cli->onConnect(cli);//调用onConnect回调函数,这时候会把自己当参数带过去
}

 

展开阅读全文

没有更多推荐了,返回首页