求解数据粘包问题,使用text协议

defeatlr

系统内核已参照手册优化,php7 已安装event扩展
硬件发送的数据格式

send 1000,86358603733073,0003,AA00000000,0003,00,0818031611,,,,0000,结束符号是\r\n

客户端测试代码

function connect()
{
    static $count = 0;
    if ($count++ >= 100) return;
    $con = new AsyncTcpConnection('text://xxxxx:8282');
    $con->onConnect = function ($con) {
        // 递归调用connect
        connect();
    };
    $con->onMessage = function ($con, $msg) {
        echo "recv $msg\n";
    };
    $con->onClose = function ($con) {
        echo "con close\n";
    };

    Timer::add(1, function () use ($con) {
//        $data = "send 1000,86358603733073,0003,AA00000000,0003,00,0818031611,,,,0000" . "\r\n";
//        for ($i=0;$i<200;$i++){
//            $data .= "send 1000,86358603733073,0003,AA00000000,0003,00,0818031611,,,,0000" . "\r\n";
//        }
        $data = "send 1000,86358603733073,0003,AA00000000,0003,00,0818031611,,,,0000" . "\r\n" . "send 2000,86358603733073,0003,AA00000000,0003,00,0818031611,,,,0000" . "\r\n";
        $con->send($data);
    });
    $con->connect();
    echo $count, "connections complete\n";
}

协议部分复制了text的协议,就改了下input方法

    public static function input($buffer, TcpConnection $connection)
    {
        if (strlen($buffer) >= TcpConnection::$maxPackageSize) {
            $connection->close();
            return 0;
        }
        // 获得换行字符"\n"位置
        $pos = strpos($buffer, "\r\n");
        // 没有换行符,无法得知包长,返回0继续等待数据
        if ($pos === false) {
            return 0;
        }
        // 有换行符,返回当前包长(包含换行符)
        return $pos + 2;
    }

Event.php onMessage方法

   public static function onMessage($client_id, $message)
    {
        var_dump($client_id . '-' .$message);
    }

运行几秒后会出现两个不同连接的数据粘一起了

string(88) "ac102fe80b5500000048-send 1000,86358603733073,0003,AA00000000,0003,00,0818031611,,,,0000"
string(88) "ac102fe80b5500000048-send 4000,86358603733073,0003,AA00000000,0003,00,0818031611,,,,0000"
string(88) "string(88) "ac102fe80b5500000048-send 1000,86358603733073,0003,AA00000000,0003,00,0818031611,,,,0000ac102fe80b5500000049-send 1000,86358603733073,0003,AA00000000,0003,00,0818031611,,,,0000"
"
string(88) "ac102fe80b5500000049-send 4000,86358603733073,0003,AA00000000,0003,00,0818031611,,,,0000"

如果客户端发送的数据改为200,打印出来直接就全部粘一起了
请问,为什么会出现这种情况?用text协议也试了,社区里问题都看遍了 ,实在不知道原因

3496 1 0
1个回答

Alu

我以前也遇到这个问题,我是这样处理的,给你参考一下:
同一个连接10ms发送一条,测试一分钟发送接收6000多条接收无误;

    public static function onMessage($Client_id, $Message)
    {
        global $global;

        if (! $Message) {
            return $global->message = null;
        }

        if (isset($global->message)) {
            $Message = $global->message . $Message;
        }

        if (! isset($Message)) {
            $global->message = $Message;
        }

        $Message = json_decode($Message, true);

    }
  • defeatlr 2018-01-04

    感谢指导!不过在群里问了下walkor他说在终端打印出来这样是正常的,顺序错乱了不算粘包,我看了下写到redis数据确实也是对的只是1秒发200条的情况下我没有仔细去核对过

年代过于久远,无法发表回答
🔝