长轮询和会话(聊天)的问题

时间:2013-07-22 12:13:24

标签: php jquery long-polling

我做了一个朋友聊天,使用文本文件存储数据,这一切都或多或少有效,除非我登录并向某人写东西,没有任何东西弹出(但文本存储在相应的文本文件中),然后当我从那时打开页面就可以了,但是在另一个浏览器上,我必须刷新页面,以便它能够双向正常工作。

基本上,每次登录时我都要点击我要聊天的人的姓名,然后会弹出一个窗口,然后我必须刷新,否则它就不会起作用。

我想每当我点击一个朋友并希望与他聊天并且这是一个会话问题时,​​我必须刷新页面。

这里是home.php(用户在登录index.php页面时被重定向到这里)

<?php
session_start();

if (!isset($_SESSION['user'])) {
    header("Location: index.php");
    exit();
}

?>
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="utf-8">

<title></title>
<style type="text/css">@import 'custom_chat.css';</style>
</head>

<body>

<h2>Hello, <?php echo $_SESSION['user']; ?></h2>
<hr>
<p><b>CONTACTS:</b></p>
<?php
require_once 'dbc.php';
$u = $_SESSION['user'];

$q = "SELECT user_id FROM users WHERE username='$u'";
$r = mysqli_query($dbc, $q);
$row = mysqli_fetch_row($r);

// current user id
$uid = $row[0];

$q = "SELECT u.username FROM users AS u, friends AS f 
      WHERE (f.f1 = '$uid' OR f.f2 = '$uid') AND (f.f1 = u.user_id OR f.f2 = u.user_id) AND (u.username != '$u')";
$r = mysqli_query($dbc, $q);


while ($row = mysqli_fetch_assoc($r)) {
    echo '<div class=chat_contacts>';
    echo '<div class='.$row['username'].'>';
    echo '<div class=inner>';
    echo '<div class=inner_chat></div>';
    echo '<form>
              <textarea class=chat_text></textarea> 
          </form>       
          ';
    echo '</div>'; // end .inner
    echo '<a href="#" class='. $row['username'] .'>'.$row['username'] .'</a>
          </div>';
    echo '</div>'; // end .chat_contacts
}

?>

<p><a href="index.php">HOME</a></p>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.18/jquery-ui.min.js"></script>
<script type="text/javascript">

var nc = '<?php echo $u ?>';

// toggle chat window
$('.chat_contacts a').click(function() {
    $(this).prev('div.inner').toggle();
    var tc = $(this).attr('class');
    $(this).parent().parent().addClass(nc+tc);
    $('textarea').focus(); // MD maybe
    return false;
});

// call main chat function
$(function () {
    updateChat(); 
}); // end ready

//update on enter
$('textarea.chat_text').keypress(function(e) {
    $this = $(this); // textarea
    if (e.which == '13') {
        insertChat();



        return false;
    }
});

function insertChat() {
    var text = $this.val();
    $this.val('');
    var ru = $this.parent().parent().parent().attr('class');
    $.post('insert.php',{text:text, ru:ru}, function(data) {
        if (data) {
            alert(data)
        }
    });
}

var timestamp = 0;
function updateChat() {
    $.ajax({
        type: 'GET',
        url: 'update.php?timestamp=' + timestamp,
        async: true,
        cache: false,

        success:function(data) {
            // alert(data);
            var json = eval('('+data+')');
            // if (json['msg'] != null) {
                $('.chat_contacts.'+nc+json['nru']+' .inner_chat').append('<p>'+json['msg']+'</p>'); // MD
            // }
            timestamp = json['timestamp'];
            setTimeout('updateChat()', 1000);
        },
        error: function(XMLHttpRequest, textStatus, errorThrown) {
            // alert('error '+textStatus+'('+errorThrown+')');
            setTimeout('updateChat()', 1000);
        }
    });
}

</script>
</body>
</html>

update.php

<?php
session_start();
require_once('dbc.php');
error_reporting(E_ALL ^ E_NOTICE);
set_time_limit(0);

$ou = $_SESSION['user'];
$ru = $_SESSION['ru'];
session_write_close();

$q = "SELECT * FROM chats WHERE 
      (chats.f1='$ru' AND chats.f2='$ou') OR (chats.f1='$ou' AND chats.f2='$ru') ORDER BY time DESC LIMIT 1";
$r = mysqli_query($dbc, $q);

// $filename = 'vojaolja.txt';
$q = "SELECT user_id FROM users WHERE username='$ou' 
      ORDER BY user_id DESC LIMIT 1";
$r = mysqli_query($dbc, $q);
$row = mysqli_fetch_row($r);
$fu = $row[0];

$q = "SELECT user_id FROM users WHERE username='$ru' ORDER BY user_id DESC LIMIT 1";
$r = mysqli_query($dbc, $q);
$row = mysqli_fetch_row($r);
$su = $row[0];

$q = "SELECT username FROM users WHERE username='$ru' ORDER BY user_id DESC LIMIT 1";
$r = mysqli_query($dbc, $q);
$row = mysqli_fetch_row($r);
$nru = $row[0];

if ($fu < $su) {
    $filename = $fu.$su.'.txt';
} else {
    $filename = $su.$fu.'.txt';
}

$lastmodif = isset($_GET['timestamp']) ? $_GET['timestamp'] : 0;
$currentmodif = filemtime($filename);

while ($currentmodif <= $lastmodif) {
    usleep(10000);
    clearstatcache();
    $currentmodif = filemtime($filename); 
}

$response = array();

$data = file($filename);
$line = $data[count($data)-1];

$response['msg'] = $line;
$response['nru'] = $nru;
$response['timestamp'] = $currentmodif;

echo json_encode($response);

?>

另外,如果有人想在他们自己的计算机上重现这个,我可以在这里发布所有代码,它只是几页,它可以在2分钟内与数据库一起设置。

编辑:

我登录后立即在控制台中看到以下内容:

http://localhost/x_super_chat/update.php?timestamp=0&_=1374509358392 (plus the rolling thingy, it is waiting)

然后我点击朋友的名字,窗口弹出,我写了一些东西,我在控制台中得到了这个:

http://localhost/x_super_chat/insert.php

然后当我重新开始工作时(当它真正开始工作时)我在控制台中得到以下内容。

http://localhost/x_super_chat/update.php?timestamp=0&_=1374509491493
http://localhost/x_super_chat/update.php?timestamp=1374509435&_=1374509493231 + the waiting thingy icon, it is waiting

所以它在刷新后会发生变化,我需要在刷新之后立即登录。

编辑2:(在Pitchinnate的回答之后)

我一登录,就会在控制台中看到这一点:

http://localhost/x_super_chat/update.php?timestamp=0&_=1374566749185 (plus the waiting animation)

然后我给对方写了一些东西(约翰说),我得到以下内容:

http://localhost/x_super_chat/update.php?timestamp=0&_=1374566749185
http://localhost/x_super_chat/insert.php
http://localhost/x_super_chat/update.php?timestamp=0&_=1374566817682
http://localhost/x_super_chat/update.php?timestamp=1374565160&_=1374566817740
http://localhost/x_super_chat/update.php?timestamp=1374566817&_=1374566817801 (plus waiting animation)

然后,当我在另一边写一些东西作为John时,我得到以下内容:(这是来自chrome,因此它与firebug中的控制台不同):

http://localhost/x_super_chat/update.php?timestamp=0&_=1374566987051
http://localhost/x_super_chat/insert.php
http://localhost/x_super_chat/update.php?timestamp=1374566995&_=1374567004175
http://localhost/x_super_chat/update.php?timestamp=1374567004&_=1374567004215

1 个答案:

答案 0 :(得分:0)

您可以尝试的一件事是在插入时取消长轮询,在更新函数var myajax;之外创建一个全局javascript变量

myajax = $.ajax({
    type: 'GET',
    url: 'update.php?timestamp=' + timestamp,

然后插入:

function insertChat() {
    myajax.abort();
    var text = $this.val();
    $this.val('');
    var ru = $this.parent().parent().parent().attr('class');
    $.post('insert.php',{text:text, ru:ru}, function(data) {
        if (data) {
            updateChat();
        }
    });
}