Потеря данных при отправке на сервер с помощью обработчика PHP - PullRequest
0 голосов
/ 02 октября 2018

Я работаю над односторонней системой обмена сообщениями, используя отправленные сервером события.У меня есть файл (server.html), который отправляет содержимое текстовой области в файл PHP (handler.php).

function sendSubtitle(val) {
    var xhr = new XMLHttpRequest();
    var url = "handler.php";
    var postdata = "s=" + val;
    xhr.open('POST', url, true);
    xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");  
    xhr.send(postdata);
    //alert(val);
}

Это работает (alert (val) отображает текст в текстовой области).

Мой код handler.php выглядит следующим образом:

header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
$stringData = $_POST['s'];

echo "data: Data is {$stringData}\n\n";
flush();

И соответствующая часть моего файла получателя SSE (client.html) выглядит следующим образом:

if(typeof(EventSource) !== "undefined") {
    var source = new EventSource("handler.php");
    source.onmessage = function(event) {
        var textarea = document.getElementById('subtitles');
        textarea.value += event.data + "<br>";
        textarea.scrollTop = textarea.scrollHeight;

    };
} else {
    document.getElementById("subtitles").value = "Server-sent events not supported.";
}

Проблема в том, что client.html отображает только «data: Data is», поэтому текст из server.html теряется где-то по пути.Я думаю, что это PHP-код, который падает, но я не могу понять, что не так.Если кто-то может помочь, я был бы признателен.

РЕДАКТИРОВАТЬ

Я решил использовать SSE, а не веб-сокеты, так как мне нужен только односторонний обмен данными: сервер.html должен помещать содержимое своей текстовой области в client.html всякий раз, когда он изменяется.Все примеры SSE, на которые я смотрел (и я много смотрел!), Отправляют «автоматические» данные, основанные на времени.Я не видел ни одного, который использует пользовательский ввод в реальном времени.Поэтому, возможно, мне следует уточнить мой первоначальный вопрос и спросить: «Как я могу использовать SSE для обновления DIV (или чего-либо еще) на веб-странице B, когда пользователь вводит текстовое поле на веб-странице A?»

UPDATE

Я сузил проблему до цикла while в файле PHP и поэтому задал новый вопрос: Страница событий сервера PHP не загружается при использовании цикла while

Ответы [ 2 ]

0 голосов
/ 03 октября 2018

Предполагая, что вы хотите отправить значение из server.html, а значение в client.html будет автоматически обновлено ...

Вам нужно будет где-то сохранить новое значение, потому что несколько экземпляров скрипта делаютне разделяйте переменные просто так.Это новое значение может быть сохранено в файле, базе данных или в качестве переменной сеанса и т. Д.

Шаги:

  1. Отправка нового значения в phpScript1 с помощью clientScript1.
  2. Сохраните новое значение с помощью phpScript1.
  3. Подключите clientScript2 к phpScript2.
  4. Отправьте сохраненное значение на clientScript2, если оно изменилось.

Получение нового значения 'на лету'означает, что phpScript2 должен зациклить выполнение и отправлять сообщение на clientScript2 всякий раз, когда значение было изменено clientScript1.

Конечно, существуют и другие подходы для достижения одинаковых результатов.

Ниже приведены некоторыекод с блокнота, который я использовал в предыдущем проекте.Большинство частей происходят из класса (который находится в разработке), поэтому мне пришлось принять довольно много кода.Также я попытался вписать его в ваш существующий код.Надеюсь, я не внес никаких ошибок.
Обратите внимание, я не принял во внимание проверку вашей ценности!Кроме того, код не отлажен и не оптимизирован, поэтому он не готов к работе.

На стороне клиента ( отправить новое значение, например, ваш код):

function sendSubtitle(val) {
    var xhr = new XMLHttpRequest();
    var url = "handler.php";
    var postdata = "s=" + val;
    xhr.open('POST', url, true);
    xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");  
    xhr.send(postdata);
    //alert(val);
}

Сторона сервера ( хранилище новое значение):

<?php
session_start();
$_SESSION['s'] = $_POST['s'];

Сторона клиента ( получить новое значение):

//Check for SSE support at client side.
if (!!window.EventSource) {
    var es = new EventSource("SSE_server.php");
} else {
    console.log("SSE is not supported by your client");
    //You could fallback on XHR requests.
}

//Define eventhandler for opening connection.
es.addEventListener('open', function(e) {
  console.log("Connection opened!");
}, false);

//Define evenhandler for failing SSE request.
es.addEventListener('error', function(event) {
    /*
     * readyState defines the connection status:
     * 0 = CONNECTING:  Connecting
     * 1 = OPEN:        Open
     * 2 = CLOSED:      Closed
     */
  if (es.readyState == EventSource.CLOSED) {
    // Connection was closed.
  } else {
      es.close(); //Close to prevent a reconnection.
      console.log("EventSource failed.");
  }
});

//Define evenhandler for any response recieved.
es.addEventListener('message', function(event) {
    console.log('Response recieved: ' + event.data);
}, false);

// Or define a listener for named event: event1
es.addEventListener('event1', function(event) {
    var response = JSON.parse(event.data);
    var textarea = document.getElementById("subtitles");
    textarea.value += response + "<br>";
    textarea.scrollTop = textarea.scrollHeight;
});

Серверсторона ( отправить новое значение):

<?php
$id = 0;
$event = 'event1';
$oldValue = null;
session_start();

//Validate the clients request headers.
if (headers_sent($file, $line)) {
    header("HTTP/1.1 400 Bad Request");
    exit('Headers already sent in %s at line %d, cannot send data to client correctly.');
}
if (isset($_SERVER['HTTP_ACCEPT']) && $_SERVER['HTTP_ACCEPT'] != 'text/event-stream') {
    header("HTTP/1.1 400 Bad Request");
    exit('The client does not accept the correct response format.');
}

//Disable time limit
@set_time_limit(0);

//Initialize the output buffer
if(function_exists('apache_setenv')){
    @apache_setenv('no-gzip', 1);
}
@ini_set('zlib.output_compression', 0);
@ini_set('implicit_flush', 1);
while (ob_get_level() != 0) {
    ob_end_flush();
}
ob_implicit_flush(1);
ob_start();

//Send the proper headers
header('Content-Type: text/event-stream; charset=UTF-8');
header('Cache-Control: no-cache');
header('X-Accel-Buffering: no'); // Disables FastCGI Buffering on Nginx

//Record start time
$start = time();

//Keep the script running
while(true){
    if((time() - $start) % 300 == 0){
        //Send a random message every 300ms to keep the connection alive.
        echo ': ' . sha1( mt_rand() ) . "\n\n";
    }

    //If a new value hasn't been sent yet, set it to default.
    session_start();
    if (!array_key_exists('s', $_SESSION)) {
        $_SESSION['s'] = null;
    }

    //Check if value has been changed.
    if ($oldValue !== $_SESSION['s']) {
        //Value is changed
        $oldValue = $_SESSION['s'];
        echo 'id: '    . $id++  . PHP_EOL;  //Id of message
        echo 'event: ' . $event . PHP_EOL;  //Event Name to trigger the client side eventhandler
        echo 'retry: 5000'      . PHP_EOL;  //Define custom reconnection time. (Default to 3000ms when not specified)
        echo 'data: '  . json_encode($_SESSION['s']) . PHP_EOL; //Data to send to client side eventhandler
        //Note: When sending html, you might need to encode with flags: JSON_HEX_QUOT | JSON_HEX_TAG
        echo PHP_EOL;
        //Send Data in the output buffer buffer to client.
        @ob_flush();
        @flush();
    }

    //Close session to release the lock
    session_write_close();

    if ( connection_aborted() ) {
        //Connection is aborted at client side.
        break;
    }
    if((time() - $start) > 600) {
        //break if the time exceeds the limit of 600ms.
        //Client will retry to open the connection and start this script again.
        //The limit should be larger than the time needed by the script for a single loop.
        break;
    }

    //Sleep for reducing processor load.
    usleep(500000);
}
0 голосов
/ 02 октября 2018

Вы вызвали handler.php в первый раз в server.html и снова в client.html.Оба разные процессы.Состояние переменной не будет сохранено на веб-сервере.Вам нужно хранить его где-нибудь, если вы хотите это значение в другом процессе PHP.Может быть, вы можете использовать сеансы или базу данных.

При использовании сеансов вы можете хранить значения в двух файлах, таких как:

<?php
//server.php
session_start();
$_SESSION['s'] = $_POST['s'];

И в файле client.php

<?php
//client.php
session_start();
echo "data: Data is ".$_SESSION['s']."\n\n";
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...