废话少说,直接上代码

<?php

define('ROOT_PATH', dirname(__file__).'/');
date_default_timezone_set('PRC');

$lang['title'] = 'PHP聊天室';

$lang['description'] = '简单的聊天室';

$lang['keywords'] = 'PHP聊天室,简单的聊天室';

$config['dataListNum'] = 30;

$config['dataDir'] = './';

$config['dataFile'] = 'data';

$action = isset($_POST['action']) ? trim($_POST['action']) : '';

function access($method, $data = '', $type = 'array')
{
global $config;

$file = ROOT_PATH.$config['dataDir'].'/'.$config['dataFile'];
if ($method == 'r') {
if (file_exists($file)) {
if ($type == 'array') {
$data = file_get_contents($file);
$data = json_decode($data, true);
$data = is_array($data) ? $data : array();
}
if ($type == 'json') $data = file_get_contents($file);
return $data;
}
if ($type == 'array') $data = array();
if ($type == 'json') $data = '';
return $data;
}
if ($method == 'w') {
$data = json_encode($data);
return file_put_contents($file, $data);
}
}

function makeDir($dir, $mode = 0777)
{
if (!is_dir($dir)) {
makeDir(dirname($dir), $mode);
return mkdir($dir, $mode);
}
return true;
}

function showIp($ip)
{
$IpArr = explode('.', $ip);
return $IpArr['0'].'.'.$IpArr['1'].'.'.preg_replace("/[0-9]/", "*", $IpArr['2']).'.'.preg_replace("/[0-9]/", "*", $IpArr['3']);
}

function ubb($ubb) {
global $lang;

$ubb = strip_tags($ubb);
$ubb = preg_replace('/\n/', '<br />', preg_replace('/ /', ' ', $ubb));
$ubb = preg_replace("/(\[url=)(.*)\](.*)(\[\/url\])/", "<a href=\\2 target=_blank>\\3</a>", $ubb);
$ubb = preg_replace("/(\[color=)(.*)\](.*)(\[\/color\])/", "<font color=\\2>\\3</font>", $ubb);
$ubb = preg_replace("/(\[size=)([0-9]*)\](.*)(\[\/size\])/", "<font size=\\2>\\3</font>", $ubb);
$ubb = preg_replace("/(\[b\])(.*)(\[\/b\])/", "<b>\\2</b>", $ubb);
$ubb = preg_replace("/(\[img\])(.*)(\[\/img\])/", "<a href=\\2 target=_blank><img src=\\2 border=0></a>", $ubb);
$ubb = preg_replace("/\[qq\]([0-9]*)\[\/qq\]/", "<a target=\"_blank\" href=\"tencent://message/?uin=\${1}&site=".$lang['title']."&menu=yes\"><img src=\"http://wpa.qq.com/pa?p=1:\${1}:8\" alt=\"QQ\${1}\" height=\"16\" border=\"0\" align=\"top\" /></a>", $ubb);
return $ubb;
}

function cutstr($string, $length, $dot = ' ...')
{
if(strlen($string) <= $length) return $string;
$string = str_replace(array('&', '"', '<', '>'), array('&', '"', '<', '>'), $string);
$strcut = '';
$n = $tn = $noc = 0;
while ($n < strlen($string)) {
$t = ord($string[$n]);
if ($t == 9 || $t == 10 || (32 <= $t && $t <= 126)) {
$tn = 1; $n++; $noc++;
} else if (194 <= $t && $t <= 223) {
$tn = 2; $n += 2; $noc += 2;
} else if (224 <= $t && $t <= 239) {
$tn = 3; $n += 3; $noc += 2;
} else if (240 <= $t && $t <= 247) {
$tn = 4; $n += 4; $noc += 2;
} else if (248 <= $t && $t <= 251) {
$tn = 5; $n += 5; $noc += 2;
} else if ($t == 252 || $t == 253) {
$tn = 6; $n += 6; $noc += 2;
} else {
$n++;
}
if($noc >= $length) {
break;
}
}
if($noc > $length) {
$n -= $tn;
}
$strcut = substr($string, 0, $n);
$strcut = str_replace(array('&', '"', '<', '>'), array('&', '"', '<', '>'), $strcut);
return $strcut.$dot;
}

function checkLen($str, $minLen, $maxLen = '')
{
$strLen = strlen($str);
if ($maxLen) {
if ($strLen < $minLen || $strLen > $maxLen) return false;
} else {
if ($strLen < $minLen) return false;
}
return true;
}

if ($action == 'write') {
$name = $_POST['name'] ? $_POST['name'] : showIp($_SERVER['REMOTE_ADDR']);
$content = ubb($_POST['content']);
if (trim($_POST['content'])) {
setCookie('chatName', $name, time() + 1 * 30 * 24 * 60 * 60 * 1000); //1个月
makeDir(ROOT_PATH.$config['dataDir']);
!checkLen($name, 0, 20) && $name = cutStr($name, 20);
!checkLen($content, 0, 1000) && $content = cutStr($content, 1000);
if (!file_exists(ROOT_PATH.$config['dataDir'].'/'.$config['dataFile'])) {
access('w', array('0' => array('name' => $name, 'content' => $content, 'time' => date('H:i:s'))));
} else {
$dataArr = access('r');
$count = count($dataArr);
if ($count >= $config['dataListNum']) {
foreach ($dataArr as $key => $value) {
if ($key >= ($count - ($config['dataListNum'] -1))) {
$data[] = $value;
}
}
} else {
$data = $dataArr;
}
array_push($data, array('name' => $name, 'content' => $content, 'time' => date('H:i:s')));
access('w', $data);
}
}
}

if ($action == 'read') {
exit(access('r', '', 'json'));
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" />
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gbk" />
<title><?php echo $lang['title']?></title>
<meta name="keywords" content="<?php echo $lang['keywords']?>" />
<meta name="description" content="<?php echo $lang['description']?>" />
<meta name="author" content="YYT" />
<style type="text/css">
*{padding:0; margin:0; list-style:none;}
body{font-family:Georgia,Times New Roman,Times,serif; font-size:12px; background:#FFF; margin:50px 0 5px; text-align:center;}
.box{width:500px; background:#F1F1F1; padding:5px; text-align:left; overflow:hidden; border:#CCC solid 1px; margin:0 auto;}
#show{background:#FFFFFF; border:#CCC solid 1px; padding:5px; overflow:auto;}
#show a{color:#000;}
.content{width:98%; overflow:hidden;}
.contentText{width:100%; border:#CCC solid 1px;}
</style>
<script type="text/javascript">
var isIE = (document.all) ? true : false;
function $(obj)
{
return document.getElementById(obj);
}

function createAjax()
{
var ajax = false;
if (window.ActiveXObject) {
var ajax = new ActiveXObject("Microsoft.XMLHTTP");
} else if(window.XMLHttpRequest) {
var ajax = new XMLHttpRequest();
}
return ajax;
}
</script>
</head>
<body>
<div>
<div id="show" style="height:320px"></div>
<p style="margin-top:5px">名称:<input type="text" name="name" value="<?php echo $_COOKIE['chatName']?>" size="10" id='name' style="border: #CCC solid 1px;"> 不写为IP (超过20个字符则省略)</p><p>内容:*不能为空 (超过1000个字符则省略) <a href='#' onclick='clearAll()'>清屏</a> <a href='#' onclick='resize(1)'>+</a> <a href='#' onclick='resize(0)'>-</a> 支持UBB代码 <br /><textarea name="content" rows="5" id="content" onkeydown="keyDown(this)"></textarea></p><p align="center"><input type="submit" value="CTRL + ENTER 提交" onclick="addPost();"></p>
</div><!--box over-->

<script type="text/javascript">
var sending = false;
var loading = false;
var maxDisplay = <?php echo $config['dataListNum']?>;
var nowDisplay = 1;
var loadedLines = [];
var lastContent;

setInterval('loadContent()', 1000);

var loadContentAjax;

function loadContentChange()
{
if (loadContentAjax.readyState == 4) {
if (loadContentAjax.status != 200) {
loadContentError();
return;
}
window.loading = false;
var body = $('show');
try {
eval('var arr = '+loadContentAjax.responseText);
} catch(e) {
return;
}

if (!arr) return;

var line = arr;
var i = 0;
var v1 = 0;

for(var i = 0; i < line.length; i++) {
var lineKey = line[i].time;
if (window.loadedLines[lineKey] === true) continue;
var div1 = document.createElement('div');
window.nowDisplay++;
if (window.nowDisplay > window.maxDisplay) window.nowDisplay = 1;
if ($('contents'+window.nowDisplay)) body.removeChild($('contents'+window.nowDisplay));
div1.className = 'content';
div1.id = 'contents'+window.nowDisplay;
div1.innerHTML = '<p style="color:blue;margin-top:5px">'+line[i].name+' '+line[i].time+'</p><p>'+line[i].content+'</p>';
body.appendChild(div1);
window.loadedLines[lineKey] = true;
body.scrollTop = 655350;
v1 = 1;
}

if (v1) {
window.focus();
with($('content')) {
disabled = false;
focus();
style.backgroundColor = '#FFFFFF';
}
}
}
}

function loadContentError()
{
window.loading = false;
window.status = 'Error 102:while loading words';
setTimeout("window.status = '';", 5000);
}

function loadContent()
{
loadContentAjax = createAjax();
if (window.loading) {
try {
loadContentAjax.abort();
window.loading = false;
}catch(e) {}
}
loadContentAjax.open('POST', '<?php echo basename(__FILE__);?>', true);
loadContentAjax.onreadystatechange = loadContentChange;
var postStr = 'action=read';
window.loading = true;
loadContentAjax.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
loadContentAjax.send(postStr);
}

var sendAjax;

sendAjaxChange  = function ()
{
if (sendAjax.readyState == 4) {
if (sendAjax.status != 200) {
sendAjaxError();
return;
}
onSendOk();
$('content').disabled = false;
$('content').focus();
}
}

function addPost()
{
var name = $('name').value;
var content = $('content').value;
if (!content) {
alert('内容不能为空');
return;
}
sendAjax = createAjax();
sendAjax.open('POST', '<?php echo basename(__file__)?>', true);
sendAjax.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
sendAjax.onreadystatechange = sendAjaxChange;

var postStr = 'action=write';
postStr += '&name='+encode(name);
postStr += '&content='+encode(content);

window.sending = true;
window.lastContent = content;
onSendBegin();

sendAjax.send(postStr);
setTimeout("if (window.sending) sendAjax.abort(); onSendError();", 5000);
}

function sendAjaxError()
{
alert('网络延迟……');
$('content').value = window.lastContent;
window.sending = false;
onSendError();
}

function onSendBegin()
{
with($('content')) {
disabled = true;
style.backgroundColor = '#EEEEEE';
}
window.sending = true;
}

function onSendError()
{
window.sending = false;
with($('content')) {
disabled = false;
focus();
style.backgroundColor = '#FFFFFF';
}
}

function onSendOk()
{
window.sending = false;
with($('content')) {
value = '';
disabled = false;
focus();
style.backgroundColor = '#FFFFFF';
}
}

function encode(str)
{
return (encodeURIComponent) ? encodeURIComponent(str) : str;
}

function keyDown(obj)
{
obj.onkeydown = function(e)
{
if (isIE) {
if (event.ctrlKey && getkeyCode(event) == 13) {
addPost();
}
} else {
if (e.ctrlKey && getkeyCode(e) == 13) {
addPost();
}
}
}
}

function getkeyCode(e)
{
var keynum = false;
if (isIE) {
keynum = e.keyCode;
} else {
keynum = e.which;
}
return keynum;
}

function resize(s)
{
var o = $('show').style;
var h = parseInt(o.height);
h = (s) ? h + 50 : h - 50;
if (h<=50 || h>=3000) return;
o.height = h;
$('show').scrollTop = 655350;
}

function clearAll()
{
$('show').innerHTML = '';
}
</script>
</body>
</html>