2011-12-13 109 views
3

我需要帮忙做在线聊天。我已经创建了一个简单的在线聊天,其中一个用户可以与另一个用户通信,他们的对话被保存为json文件。 json文件是我在每2secs后使用setInterval()重新加载的内容。用户发送的消息通过使用ajax并通过php函数fopen和fwrite(附加)发布,附加在json文件上。使用池共享在线聊天

我的问题是,我的ajax发送/发布过程太慢了。在用户看到他/她的消息在聊天屏幕(div)上发送之前需要时间。我尝试在屏幕上追加消息,看起来好像它已经发送了,但问题是当setInterval重新加载聊天屏幕并且新增加的消息尚未保存在json文件中时,新发送的消息将不会包含在重新加载。

问题:

  1. 我怎么能追加新的消息更快?
  2. 当用户打字并发送信息太快时,如何将多个帖子排列在我的ajax上?
  3. PS:他们是创建在线聊天的更好方式吗?我读过,我正在使用我的聊天池,更好的方式是使用套接字,但我不知道如何使用它。你有更好的方式还是更好的逻辑?
+2

你没有使用数据库的原因?这会容易得多。 – Ryan

+0

我没有使用数据库,因为我认为保存每条消息将填充我的数据库。 –

+0

它会填充你的数据库:''它不会占用太多的空间 - 大概比平面文件多32KB - 你会享受到好处。 – Ryan

回答

4

几点考虑:

- >搜索约长轮询(COMET)

- >为什么setInterval的刷新屏幕,它应该只是从服务器追加新的消息

- >如果您使用基于HTML5的浏览器,请检查Websockets和服务器端事件。

- >在服务器端使用数据库操作,而不是文件操作。它还会提高可维护性,考虑1000个不同用户正在聊天的情况,这些文件很难维护。

- >服务器应该发送新的增量消息,它不应该只是再次发送整个会话到客户端解析和重新加载。

+1

另外使用数据库可能会比XML或JSON对象更快。 – c0d3Junk13

+0

是的,追加比刷新整个页面更好。谢谢!关于websockets,我不能使用它,因为我需要HTML5,而且它们是用户不使用它的大好机会。 –

+0

我同意数据库应该更快,然后文件操作...谢谢c0d3Junk13。 –

0

我只是做了最近,这里是代码

的index.php

<?php 
    session_start(); 

    if(isset($_GET['logout'])) { 
     session_destroy(); 
     header("Location: index.php"); // 
    } 

    if(isset($_POST['username'])) { 
     if(trim($_POST['username']) != "") { 
      $_SESSION['username'] = stripslashes(htmlspecialchars($_POST['username'])); 
      header("Location: index.php"); // 
     } else { 
      header("Location: index.php"); // 
     } 
    } 
?> 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml" lang="zh-CN"> 
<head profile="http://gmpg.org/xfn/11"> 
<title>chating</title> 
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 
<link rel="stylesheet" href="style.css" type="text/css" media="screen" /> 
<script type="text/javascript" src="jquery-1.5.min.js"></script> 
<!--[if IE]> 
<script type="text/javascript" src="jquery.corner.js"></script> 
<script type="text/javascript"> 
$("#main,#login").corner("15px"); 
</script> 
<![endif]--> 

<script type="text/javascript"> 
//<![CDATA[ 
$(document).ready(function() { 

    //$("#main,#login").corner(); 

    $("#message").focus(); 

    $("#logout").click(function() { 
     if(confirm("Are you sure to exit this chat?")) { 
      window.location = "index.php?logout=yes"; 
     } 
    }); 

    $("#btnsend").click(function() { 

     //$("#chathistory").append("<div>" + $("#message").val() + "</div>"); 
     //alert($("#chathistory").html()); 

     if($("#message").val() == "") { 
      alert("Please input something !"); 
      return false; 
     } 

     $.post("ajax.php", {message: $("#message").val()}); 

     $("#message").val(""); 
     $("#message").focus(); 

     return false; 
    }); 

    $("#message").keydown(function(e) { 
     if (e.ctrlKey && e.keyCode == 13) { 
      $("#btnsend").click(); 

     } 
     //alert(e.keyCode); 
    }); 


    function loadChatHistory() { 
     var oldscrollHeight = $("#chathistory").attr("scrollHeight") - 20; 

     $.ajax({ 
      url: "ajax.php?type=getmsg", 
      cache: false, 
      dataType: "xml", 
      success: function(xmlData) { 

       var htmlData = ""; 
       $(xmlData).find("Msg").each(function() { 
        htmlData += '<div><span class="people">' + $(this).find("MsgFrom").text() + " " + $(this).find("MsgDateTime").text() + '</span><p class="content">' + $(this).find("Message").text() + '</p></div>' 
       }); 

       $("#chathistory").html(htmlData); 
       var newscrollHeight = $("#chathistory").attr("scrollHeight") - 20; 

       if(newscrollHeight > oldscrollHeight) { 
        $("#chathistory").animate({ scrollTop: newscrollHeight }, 'normal'); 
       } 

      } 
     }); 




    } 

    setInterval (loadChatHistory, 2500); 
}); 
//]]> 
</script> 
</head> 
<body> 
<?php 
    //print_r(var_dump($_SESSION)); 
?> 
<?php 
    if(!isset($_SESSION['username'])) { 
?> 
    <div id="login"> 
     <form action="index.php" method="post"> 
      <label for="username">UserName:</label> 
      <input type="text" id="username" name="username" class="corner2"/> 
      <input type="submit" id="btnlogin" name="btnlogin" class="corner2" value="Login"/> 
     </form> 
    </div> 
<?php 
    } else { 
?> 
    <div id="main"> 

     <p id="welcome">Welcome, <strong><?php echo $_SESSION['username'] ?></strong></p> 
     <p id="logout"><a href="#">Exit Chat</a></p> 
     <div class="clear"></div> 
     <div id="chathistory" class="corner2"> 

     </div><!-- #chathistory --> 

     <div id="userlist" class="corner2"> 

     </div><!-- #userlist --> 

     <div id="chatarea" class="corner2"> 
      <textarea id="message" class="corner2" rows="2" cols="2"></textarea> 
     </div><!-- #chatarea --> 
     <div id="send"> 
      <input type="button" id="btnsend" value="Send!" class="corner2" /> 
     </div> 
     <div class="clear"></div> 

    </div><!-- #main --> 
<?php 
    } 
?> 
</body> 
</html> 

ajax.php

<?php 

    session_start(); 
    date_default_timezone_set("PRC"); 

    if(isset($_SESSION["username"])) { 
     $dbh = new pdo("sqlite:./Message.DB"); 

     if(isset($_GET["type"])) 
     { 

      if($_GET["type"] == "getmsg") { 

       $strXML = '<?xml version="1.0" encoding="utf-8" ?>'; 
       $strXML .= "<Msgs>"; 

       foreach($dbh->query("select * from (SELECT * FROM Message ORDER BY MsgID DESC limit 0,500) ORDER BY MsgID ASC") as $row) { 
        $strXML .= "<Msg>"; 
        $strXML .= " <Message>" . stripslashes(htmlspecialchars($row[1])) . "</Message>"; 
        $strXML .= " <MsgDateTime>" . $row[2] . "</MsgDateTime>"; 
        $strXML .= " <MsgFrom>" . stripslashes(htmlspecialchars($row[3])) . "</MsgFrom>"; 
        $strXML .= "</Msg>"; 
       } 

       $strXML .= "</Msgs>"; 
       echo $strXML; 

      } 
     } else { 

      $message = $_POST["message"]; 
      $message = str_replace("'","''",$message); 

      $SQL = "INSERT INTO Message(Message, MsgDateTime, MsgFrom) VALUES('" . $message . "', '" . date("Y-m-d H:i:s") . "','" . str_replace("'","''",$_SESSION["username"]) . "')"; 
      //echo $SQL; 
      $dbh->query($SQL); 
     } 
    } 
?> 

风格。CSS

* { 
    margin: 0; 
    padding: 0; 
} 

body { 
    font-family: LucidaGrande, Tahoma, Verdana, Arial, IPAPGothic, sans-serif; 
    font-size: 14px; 
    line-height: 1.5; 
    background-color: #EDE8E2; 
} 



#main ,#login { 
    width: 600px; 
    margin: 30px auto; 
    padding: 20px; 
    background-color: #A8B6D3; 

    -moz-box-shadow: 10px 10px 5px #888888; 
    -webkit-box-shadow: 10px 10px 5px #888888; 
    box-shadow: 10px 10px 5px #888888; 

    -moz-border-radius:15px; 
    border-radius:15px; 
} 

#login { 
    text-align:center; 
} 

#login input[type="text"] { 
    border:0; 
    padding:5px; 
} 

#login input[type="submit"] { 
    border:0; 
    border:2px solid #5D92D0; 
    background-color: #A8B6D3; 
    padding:2px; 
    font-family: LucidaGrande, Tahoma, Verdana, Arial, IPAPGothic, sans-serif; 
    font-size: 14px; 
} 

#welcome { 
    margin-bottom: 10px; 
    float:left; 
} 

#logout { 
    text-align:right; 
    font-weight:bold; 
} 

#chathistory { 
    background-color: #fff; 
    width: 450px; 
    height: 250px; 
    padding: 4px 10px; 
    float: left; 
    overflow: auto; 
} 

#chathistory span.people { 
    color:#008040; 
    margin-right:10px; 
} 

#chathistory p.content { 
    margin-left:20px; 
} 

#userlist { 
    background-color: #fff; 
    margin-left: 480px; 
    padding: 4px 10px; 
    width:100px; 
    height: 250px; 
    overflow: auto; 
} 

#userlist ol { 
    list-style-type: none; 
} 

#chatarea { 
    background-color: #fff; 
    margin-top:15px; 
    height:70px; 
    width:470px; 
    padding: 0; 
    float:left; 
} 

#message { 
    width: 460px; 
    height:62px; 
    resize: none; 
    border: 0; 
    padding: 4px 0 4px 10px; 

    font-family: LucidaGrande, Tahoma, Verdana, Arial, IPAPGothic, sans-serif; 
    font-size: 14px; 
    line-height: 1.4; 

    overflow:auto; 
} 

#btnsend { 
    width:120px;; 
    height:70px; 
    margin-left: 10px; 
    margin-top:15px; 
    border:2px solid #5D92D0; 
    background-color: #A8B6D3; 
    font-family: LucidaGrande, Tahoma, Verdana, Arial, IPAPGothic, sans-serif; 
    font-size: 28px; 
    font-weight:bold; 
} 

.corner2 { 
    -moz-border-radius:5px; 
    border-radius:5px; 
} 

.clear { 
    clear:both; 
} 

PS,我USD SQLite数据库

0

你应该使用一个数据库,而不是一个平面文件好像试图同时读写文件可能有问题,这需要不必要的处理每隔两秒解析整个json格式的对话,我建议使用sqlite,因为它很容易设置,并且不需要任何特殊的数据库服务器软件,因此您可以执行一个查询来选择当前会话之后发送的所有消息上次刷新时,您的查询将沿着以下线路进行:

提取消息:

mysql_query("SELECT * FROM `chat` WHERE `id` == '".$id."' AND `timestamp` > '".$lastfetch."'"); 

发送消息:

$timestamp = time(); 
mysql_query("INSERT INTO `chat` (`id`,`message`,`timestamp`) VALUES('".$convoid."', '".$message."', '".$timestamp."')"); 
echo $timestamp; 

你会然后保存呼应时间戳到您的javascript中的变量,然后用你的下一个AJAX获取将其作为$lastfetch,所以您的查询将得到所有新自上次检查以来的消息。