2011-12-13 108 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,所以您的查詢將得到所有新自上次檢查以來的消息。