package_length_func

设置长度解析函数,支持C++PHP2种类型的函数。长度函数必须返回一个整数。

  • 返回0,长度数据不足,需要接收更多数据
  • 返回-1,数据错误,底层会自动关闭连接
  • 返回包长度值(包括包头和包体的总长度),底层会自动将包拼好后返回给回调函数

使用方法

实现原理是先读取一小部分数据,在这段数据内包含了一个长度值。然后将这个长度返回给底层。然后由底层完成剩余数据的接收并组合成一个包进行dispatch

PHP长度解析函数

由于ZendVM不支持运行在多线程环境,因此底层会自动使用Mutex互斥锁对PHP长度函数进行加锁,避免并发执行PHP函数。在1.9.3或更高版本可用。

请勿在长度解析函数中执行阻塞IO操作,可能导致所有Reactor线程发生阻塞

$serv = new Swoole\Server("127.0.0.1", 9501);

$serv->set(array(
    'open_length_check' => true,
    'dispatch_mode' => 1,
    'package_length_func' => function ($data) {
        if (strlen($data) < 8) {
            return 0;
        }
        $length = intval(trim(substr($data, 0, 8)));
        if ($length <= 0) {
            return -1;
        }
        return $length + 8;
    },
    'package_max_length' => 2000000,  //协议最大长度
));

$serv->on('receive', function (swoole_server $serv, $fd, $from_id, $data)
{
    var_dump($data);
    echo "#{$serv->worker_id}>> received length=" . strlen($data) . "\n";
});

$serv->start();

C++长度解析函数

在其他PHP扩展中,使用swoole_add_function注册长度函数到Swoole引擎中。

C++长度函数调用时底层不会加锁,需要调用方自行保证线程安全性

实例:

#include <string>
#include <iostream>
#include "swoole.h"

using namespace std;

int test_get_length(swProtocol *protocol, swConnection *conn, char *data, uint32_t length);

void register_length_function(void)
{
    swoole_add_function((char *) "test_get_length", (void *) test_get_length);
    return SW_OK;
}

int test_get_length(swProtocol *protocol, swConnection *conn, char *data, uint32_t length)
{
    printf("cpp, size=%d\n", length);
    return 100;
}


  • ¥黑眼黑猫@

    package_length_func这边有误 按照pack('N',strlen($str)) . $str 这种发数据 设置的时候应该 'package_length_func' => function ($data) { if (strlen($data) < 4) { return 0; } elseif (strlen($data) == 4) { return -1; } else { return unpack('N',substr($data,0,4))[1] + 4; } },