我一直致力于快速简单的jQuery / PHP聊天,放在我的网站上供访问者进行交流。我估计有200个同步网站用户(连接用户)的峰值,其中最多有10-20人实际聊天。
这是怪癖:
我已经经历了两次(认为这似乎是一个不太可能的事件,而不是在你执行某些特定事情之后发生的事情)聊天恰好加载了多条消息,这些消息已经是红色并显示它们。
尽量保持聊天系统尽可能简单我想出了这段代码:
HTML CODE:
<div class="chat">
<ul class="chat">
<li class="chat" >
<h5 class="chat">Date</h5>
<h6 class="chat">Time</h6>
<h4 class="chat">User</h4>
<br/>
<q class="chat">Message</q>
</li>
</ul>
<input class="chat" placeholder="write something..."/>
</div>
正如您所看到的,我为jQuery添加了一个占位符 li 元素,并将其用作使用实际消息和创建新 li 元素的代码段。在 ul 元素中添加它们。
jQuery CODE:
发送消息:
$(document).ready(function(){
chatSnippet = $('ul.chat').html(); // here chatSnippet is a global variable
$('ul.chat').html('');
$('input.chat').change(function(event){// Send your message
message = $(this).attr('value');
// first thing I perform an asynchronous POST to the receiving php script
$.post(
'php/chatRec.php',
{
user : currentUser,
message: message,
}
);
// meanwhile I add a new li element to the chat html with the content just submitted
date.setTime(event.timeStamp);
hours = ''+date.getHours();
if(hours.length < 2) hours = '0'+hours;
minutes = ''+date.getMinutes();
if(minutes.length < 2) minutes = '0'+minutes;
day = ''+date.getDate();
if(day.length < 2) day = '0'+day;
newChatMessage = chatSnippet.replace('Date', ''+day+' '+months[date.getMonth()]);
// here months is an array with the months names (in italian)
newChatMessage = newChatMessage.replace('Time', ''+hours+':'+minutes);
newChatMessage = newChatMessage.replace('User', connectedUser);
newChatMessage = newChatMessage.replace('Message', message);
$mess = $(newChatMessage);
$mess.hide().prependTo('ul.chat').fadeIn(500);
$(this).attr('value','');
});
refreshChat(''); // this function retrives new messages from the DB
// Here I perform a void refreshChat call so I'll get all the messages in the DB regardless from the currentUser (at page refresh)
});
接收消息:
// This code is placed outside (before) the .ready function
function refreshChat(user){// Receiving messages
$.post(
'php/chatInv.php',
{
user : user,
token: lastMessage // this variable contains the token of the last red message
},
function(data){
receivedMessages = jQuery.parseJSON(data);
for(message in receivedMessages){
message = receivedMessages[message].Message;
date = receivedMessages[message].Day.split('-');
time = receivedMessages[message].Time.split(':');
newChatMessage = chatSnippet.replace('Date', ''+date[2]+' '+months[parseInt(date[1])-1]);
newChatMessage = newChatMessage.replace('Time', ''+time[0]+':'+time[1]);
newChatMessage = newChatMessage.replace('User', receivedMessages[message].Sender);
newChatMessage = newChatMessage.replace('Message', message);
$mess = $(newChatMessage);
$mess.hide().prependTo('ul.chat').fadeIn(500);
lastMessage = receivedMessages[messages].token;
}
nextRefresh = setTimeout("refreshChat('"+currentUser+"')",2000);
// When I'm done I set a timeout of 2 secs and then perform another refresh
}
);
}
PHP代码:
收到新消息(我认为问题在这里):
mysql_connect("localhost", "root", "root") or die(mysql_error());
mysql_select_db("chat") or die(mysql_error());
$characters = array('0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z');
$token = $characters[rand(0,61)].$characters[rand(0,61)].$characters[rand(0,61)].$characters[rand(0,61)].$characters[rand(0,61)];
$all_Msgs = mysql_query("SELECT * FROM Messages ORDER BY ID");
$prev_Msg = array('ID' => 1 , 'Sender' => $_POST['user'], 'Message' => $_POST['message'], 'Day' => date("Y-m-d"), 'Time' => date("H:i:s"), 'token' => $token);
while($Msg = mysql_fetch_array($all_Msgs)){
$update_success = mysql_query("UPDATE Messages SET Sender='".$prev_Msg['Sender']."', Message='".$prev_Msg['Message']."', Day='".$prev_Msg['Day']."', Time='".$prev_Msg['Time']."', token = '".$prev_Msg['token']."' WHERE ID=".$Msg['ID']);
$prev_Msg = $Msg;
}
基本上我在这里做的是接收新的帖子消息,生成一个令牌和一个包含新输入数据的数组元素(它本身就是一个数组),这样做我在一个固定大小的SQL表上执行UPDATE语句的seuqence覆盖第一条记录上的新数据,然后用前一条记录覆盖每条记录(以便最后一条记录最终丢失)。
发送消息:
mysql_connect("localhost", "root", "root") or die(mysql_error());
mysql_select_db("chat") or die(mysql_error());
$receiver = $_POST['user'];
$token = $_POST['token'];
$all_Msgs = mysql_query("SELECT * FROM Messages ORDER BY ID");
$newMessages = array();
while($Msg = mysql_fetch_array($all_Msgs)){
if($Msg['token'] == $token) break;
if($Msg['Sender'] != $receiver) array_unshift($newMessages,$Msg);
}
echo json_encode($newMessages);
因此,我向客户端发送JSON编码,该编码包含在最后一条已知消息之后插入的数据库中的所有记录,并且其作者不是查询客户端。
我的嫌疑人:
我得出的结论是,当正在执行消息接收(服务器端)时,每个消息都从DB中获取时间跨度,如果同时执行刷新,则找不到消息,如果该消息是我们正在寻找的最后一条红色消息,然后服务器将只选择表中的所有消息并将其发回。
结果是你看到一堆消息你已经红了没有你的消息(因为它们被添加到视图客户端而服务器脚本没有发回你自己的消息)
说明:
您认为我对问题的解释是对的吗? 如果不是:那将是什么原因? /我该如何解决? 如果是:我怎样才能轻松解决这个问题?
如果实际修复相当复杂:实际可能发生的情况是10-20个用户聊天中的这个怪癖?
由于
答案 0 :(得分:1)
当我处理聊天代码时,我注意到了这一点,解决方案是在会话中存储最后一条消息ID(在MySQL中设置为自动增量字段),并在数据库中搜索ID高于该值的消息,而不是使用time()函数。
if (!$_SESSION['message_id']]) {
// if there isn't a message_id, select the last seven entries in the message list
$sql = "SELECT messages.message_id, messages.message, users.username FROM (SELECT * FROM messages, users user.user_id = messages.user_id ORDER BY message_id DESC LIMIT 7) as new_tbl ORDER BY message_id ASC";
} else {
// if there is a message_id, select the messages sent since the last entry
$sql = sprintf("SELECT messages.message_id, messages.message, users.username FROM messages, users WHERE user.user_id = messages.user_id message_id > '%d'", $_SESSION['message_id']);
}
$data = array();
$query = mysql_query($sql);
while ($row = mysql_fetch_array($query)) {
// build the data array from the mysql result and set the message_id session to the id of the last message
$data[$i] = array('user' => $row['username'], 'message' => $row['message']);
$_SESSION['message_id'] = $row['message_id'] > $_SESSION['message_id'] ? $row['message_id'] : $_SESSION['message_id'];
$i++;
}
显然你需要逃避会议!
如果没有message_id会话,它会从表中加载最后7条消息(按降序排序,然后按升序对这些消息进行排序)。如果有message_id会话,则会加载新消息。
在while循环中,它构建一个数据数组(我将其作为JSON发送到我的脚本)并将message_id会话设置为message_id行,并进行故障安全检查以确保message_id会话不会最终降低
SQL意味着您拥有一个包含user_id和username的用户表,以及一个包含user_id,message_id和message的消息表。