[英]PHP Websocket Client - Keep connection open
我在 Laravel 应用程序中使用PHP-WSS ,需要保持 websocket 客户端打开以接收来自 websocket 服务器的各种消息。
到目前为止,我构建了一个 CLI php 脚本,我可以执行该脚本并等待消息到达。
我构建了以下功能来测试...
问题是,要保持连接对可能从服务器发送的任何消息保持打开状态,使用 while(true) 循环执行以下操作是否是一种好方法? 无论如何我可以做得更好吗? (对我来说它看起来很脏,希望改进它并正确地做)
function testWebsocketClient() {
$url = 'wss://example.com/?token=xyz123456';
$client = new WebSocketClient($url, new ClientConfig());
while(true){
sleep(5);
$client->send('test');
$return = $client->receive(); // test received OK
}
return $return;
}
更新:任何使用 PHP-WSS 的人我在 BroadCast 方法中的 Connection.php 中发现了一个错误。
原始函数尝试在死连接上发送,显示以下错误 Empty read; 连接死了? (注意EOF = true)
public function broadCast(string $data): void
{
foreach ($this->clients as $client) {
if (is_resource($client) ) { // check if not yet closed/broken etc
fwrite($client, $this->encode($data));
} else {
echo 'Skipping a closed connection';
}
}
}
我把它改成
public function broadCast(string $data): void
{
foreach ($this->clients as $client) {
//echo PHP_EOL. stream_get_status($client) .PHP_EOL;
$clientMeta = ( stream_get_meta_data($client) );
$clientEof = $clientMeta['eof'];
if (is_resource($client) && $clientEof == false ) { // check if not yet closed/broken etc
fwrite($client, $this->encode($data));
} else {
echo 'Skipping a closed connection';
}
}
}
由于渲染页面的php脚本执行完毕,需要在客户端自己使用js脚本实现websockets
<?php
// here output your page
wss_path = 'wss://example.com/?token=xyz123456';
?>
// JS script (see its working results in console by pressing `F12`)
<script>
let socket = new WebSocket(<?= wss_path ?>);
socket.onopen = function(e) {
console.log('[open] Connection opened');
socket.send("Hi! I am a new web-socket client.");
};
socket.onmessage = function(event) {
const message = JSON.parse(event.data);
console.log('From the server:', message);
};
socket.onclose = function(event) {
if (event.wasClean) {
console.log(`[close] Connetion closed clearly, code=${event.code} reason=${event.reason}`);
} else {
console.log('[close] Сonnection closed unexpectedly');
}
};
socket.onerror = function(error) {
console.log(`[error] ${error}`);
};
</script>
经过整整一周的努力,我找到了一个解决方案......
如果缓冲区为空,则有一个错误处理程序会引发异常,从而使客户端结束。
在 WscMain.php 文件中,在受保护的函数读取方法中,删除/注释掉(或根据您的喜好和需要更改)以下错误处理程序(大约第 302 行)
if(false){ // added a false condition so the code within doesn't execute
if (false && $buff === false ) {
$metadata = stream_get_meta_data($this->socket);
throw new ConnectionException(
'Broken frame, read ' . strlen($data) . ' of stated '
. $len . ' bytes. Stream state: '
. json_encode($metadata),
CommonsContract::CLIENT_BROKEN_FRAME
);
}
if (false && $buff === '') {
//print_r($this->socket);
$metadata = stream_get_meta_data($this->socket);
throw new ConnectionException(
'Empty read; connection dead? Stream state: ' . json_encode($metadata). ' '.PHP_EOL.( (int) $this->socket ) ,
CommonsContract::CLIENT_EMPTY_READ
);
}
}
PS:对于我的情况,我还在配置中设置了一个非常小的(1 秒)读取超时,如下所示。 (此测试函数是从 CLI PHP 脚本执行的)
function runWebsocketClientTest(){
echo PHP_EOL;
echo __FUNCTION__;
echo PHP_EOL;
$timeout = 1;
$return = '';
$config = new ClientConfig();
$config->setTimeout($timeout);
$client = new WebSocketClient('ws://localhost:8000', $config);
while($client->isConnected()){
if($client->isConnected()){ // this might be unnecessary
echo $client->receive();
}
}
}
希望这对某人有所帮助,并感谢所有提供帮助的人。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.