共计 1610 个字符,预计需要花费 5 分钟才能阅读完成。
由于长度不一致,导致判断内容是否完整失效 (没有主动关闭) 而连接超时失败 ( 造成这种现象要你的数据包够长服务端会分段获取内容). 下面这段代码是客户的事例:
$ip = '127.0.0.1';
$swoole = new swoole_client(SWOOLE_TCP);
$swoole->connect($ip, 9201, 10);
$content = str_repeat('Hello world', 1000);
// 包长在加包数据
//@see http://php.net/manual/en/function.pack.php
echo strlen($content);
$data = pack('Na*', strlen($content), $content);
$swoole->send($data);
$swoole->close();
下面是服务端代码:
$http = new swoole_server("0.0.0.0", 9201, SWOOLE_BASE, SWOOLE_SOCK_TCP);
$http->set(['worker_num' => 4,
'daemonize' => false,
/**
'package_max_length' => 1024 * 1024 * 2,
'open_length_check'=> true,
'package_length_offset' => 0,
'package_body_offset' => 4,
'package_length_type' => 'N'
**/
]);
$http->on('connect', function($serv, $fd) {echo "client connection\n";
});
$datas = ['len' => [], 'data' => []];
$http->on('receive', function(swoole_server $serv, $fd, $from_id, $data) use(&$datas) {$arr = unpack("Nlen/a*string", $data);
if (!isset($datas['len'][$fd])) {$datas['len'][$fd] = $arr['len'];
}
if (!isset($datas['data'][$fd])) {$datas['data'][$fd] = $arr['string'];
} else {$datas['data'][$fd] .= $arr['string'];
}
$len = $datas['len'][$fd];
$strlen = strlen($datas['data'][$fd]);
echo $len, PHP_EOL;
echo $strlen, PHP_EOL;
if ($strlen >= $len) {$serv->send($fd, $datas['data'][$fd], $from_id);
unset($datas['len'][$fd]);
unset($datas['data'][$fd]);
$serv->close($fd);
}
});
$http->on('close', function($serv, $fd) {echo "exit... \n";
});
$http->start();
执行结可以看到数据大小为 2W 字节, 但是服务器拼接大小后只有 19992 字节了.
开启以下代码:
$http->set(['worker_num' => 4,
'daemonize' => false,
'package_max_length' => 1024 * 1024 * 2,
'open_length_check'=> true,
'package_length_offset' => 0,
'package_body_offset' => 4,
'package_length_type' => 'N'
]);
意思是设置长度检查,长度开始位置,长度偏移量为 4 个字节,我们 N 为整型 4 个字节.
设置之后的结数据是一次性接收完整.
正文完