我已經成功實現了下一個方案:一個php套接字服務器腳本,它向所有連接的客戶端腳本廣播消息,並且這些客戶端腳本由前端腳本上的事件源監聽。所以,基本上,方案是:server.php
- >client.php
- >front.php
。套接字服務器+事件源魔法斷開連接
但我一直在努力與這部分從client.php
:
while(TRUE)
{
$read = array();
$read[] = $client_socket;
if(socket_select($read, $write, $except, 10) === FALSE){
$errorcode = socket_last_error();
$errormsg = socket_strerror($errorcode);
file_put_contents("select_result.log", "Could not listen on socket : [$errorcode] $errormsg".PHP_EOL);
}
if(!($client_message = @socket_read($client_socket, 1024))){
$errorcode = socket_last_error();
$errormsg = socket_strerror($errorcode);
file_put_contents("read_result.log", "Couldn't read socket: [$errorcode] $errormsg".PHP_EOL, FILE_APPEND);
}
if($client_message == FALSE) {
$client_message = "event: keep_alive" . PHP_EOL
. "data: keep_alive" . PHP_EOL . PHP_EOL;
}
echo $client_message;
if(ob_get_level() > 0) ob_flush();
flush();
}
當打開front.php
腳本(使用事件源)瀏覽器,它工作正常,但它也莫名其妙檢測到斷開連接,當我關閉或重新加載瀏覽器窗口中的front.php
。下面是部分從server.php
檢測斷開:
if(!($client_input = @socket_read($client, 1024))) {
$errorcode = socket_last_error();
$errormsg = socket_strerror($errorcode);
echo "$errorcode".PHP_EOL;
}
if ($client_input === FALSE) {
$socket_key = array_search($client, $client_sockets);
socket_getpeername($client, $client_address, $client_port);
socket_close($client);//?!!!
unset($client_sockets[$socket_key]);
echo "[$client_address : $client_port disconnected]".PHP_EOL;
}
正如你看到的,出現這種情況時,數據不能從客戶端讀取。從理論上講,當我關閉front.php
,client.php
應該仍然在後臺無限循環中工作,因爲我沒有任何循環中斷,但是 - 意外! - 它停止。在實驗中,我發現這是由於ob_flush()
函數造成的。發表評論時,server.php
未檢測到斷開連接(瀏覽器窗口關閉/重新加載)。怎麼會這樣?根據手冊,ob_flush()
不返回任何價值。沒有檢測到錯誤...我不知道該怎麼想,也找不到爲什麼會發生這種情況。請幫忙。
「front.php」是包含JavaScript等的HTML頁面。這個問題真的可以稱爲「front.html」嗎? (或者,您的HTML客戶端使用EventSource連接到front.php?)。換句話說,在你的瀏覽器運行的JavaScript中,你是做'新的EventSource(「client.php」)'還是做'new EventSource(「front.php」)? –
你是對的,是的,它可以很容易地稱爲'front.html',並且我做'新的EventSource(「client.php」)'; 'client.php'然後打開到'server.php'的套接字連接。 – Nevertheless