如何用PHP制作聊天室脚本?

时间:2009-04-21 13:01:47

标签: php chatroom

有多位访问者连接到http://site.com/chat.php

他们每个人都可以编写短信并发送到chat.php,它会立即显示在每个人的浏览器上(http://site.com/chat.php

我必须使用数据库吗?我的意思是,AJAX或PHP缓冲功能是否足以满足会话中的聊天室的需要?

不同用户的会话如何彼此共享数据?

任何想法或见解都将不胜感激,谢谢!

编辑:感谢您的链接。但我想要的是将数据推送到客户端浏览器的方式。是不断刷新客户端浏览器(AJAX与否)的唯一方法?此外,这里的挑战是不同的用户(例如,2,1对1)如何共享聊天文本?你如何存储它们?你如何在两个客户之间同步文本?最好不要使用数据库。

编辑2:实际上,Peter D提到的YShout做得很好。它似乎不会继续刷新浏览器。但我不明白它是如何将新消息推送到现有用户的窗口的。

6 个答案:

答案 0 :(得分:17)

创建聊天应用程序有(大约)3个选项:

插座

  

为前端使用flash / java和套接字,为后端使用支持套接字的编程语言。对于后端,我建议使用java或python,因为它们具有多线程和NIO功能。它可以用PHP来实现(但是php不能真正做到高效的多线程,并且通常不适合这个)。如果您需要高性能,而且可能不是您想要的,那么这是一个选项。

使用ajax并拉

  

在这种情况下,如果发生了新的事情,所有客户端都会不断(例如,2秒钟)进行轮询。这感觉很奇怪,因为你只能在这些间隔得到答复。另外,它给你的服务器和带宽带来了很大的压力。你知道一个应用程序使用这种技术,因为浏览器不断刷新。这是次优解决方案。

使用ajax并按

  

这适用于多部分响应,并在后端运行长时间(php-)脚本。不是最好的解决方案,但大部分时间它比拉动更好,它可以工作,并在几个众所周知的聊天应用程序中使用。这种技术有时被称为COMET

我的建议:如果您需要用于生产用途的聊天应用,请安装现有应用。编程聊天应用程序不是容易。

如果您只想学习它,请从一个简单的ajax / pull应用程序开始,然后尝试使用ajax和push编程。

是的,很可能你需要一个数据库,我很难成功实现一个非常简单的ajax / pull解决方案,它可以与文本文件一起使用(但我当然不会在生产中使用它!)。

(据我所知,但我很确定)不可能在没有服务器端后端的情况下创建聊天应用程序(仅使用前端javascript)!

更新

如果您想知道数据推送是如何完成的,请查看此处的来源:http://wehrlos.strain.at/httpreq/client.html。 async multipart就是你想要的:)

function asSendSyncMulti() {
    var httpReq = new XMLHttpRequest();

    showMessage( 'Sending Sync Multipart ' + (++this.reqCount)  );

    // Sync - wait until data arrives
    httpReq.multipart   = true;     
    httpReq.open( 'GET', 'server.php?multipart=true&c=' + (this.reqCount), false );
    httpReq.onload = showReq;
    httpReq.send( null );
}

function showReq( event ) {
    if ( event.target.readyState == 4 ) {
        showMessage( 'Data arrives: ' + event.target.responseText );
    }
    else {
        alert( 'an error occured: ' + event.target.readyState );
    }

}
每次数据到达时,showReq都被称为,而不仅仅是常规ajax请求中的一次(我不是在这里使用jquery或prototype,所以代码有点肥胖 - 这真的很旧: ))。

这是服务器端部分:

<?php

    $c = $_GET[ 'c' ];

    header('Content-type: multipart/x-mixed-replace;boundary="rn9012"');

    sleep( 1 );

    print "--rn9012\n";
    print "Content-type: application/xml\n\n";
    print "\n";
    print "Multipart: First Part of Request " . $c . "\n";
    print "--rn9012\n";
    flush();

    sleep( 3 );

    print "Content-type: application/xml\n\n";
    print "\n";
    print "Multipart: Second Part of Request " . $c . "\n";
    print "--rn9012--\n";

?>

UPDATE2

关于数据库:如果后端有mod_php / cgi之类的无共享体系结构,那么 definitley 需要某些类外部存储,如数据库或文本文件。但是:您可以通过编写自己的http服务器来依赖内存(可能使用php,但我不推荐它用于认真的工作)。这并不是很复杂,但可能有点超出了你的问题的范围^^

UPDATE3

我犯了一个错误!让一切都搞砸了,因为很长一段时间我真的做了类似的事情。以下是更正:

  1. 多部分响应仅适用于Mozilla浏览器,因此使用受限。 COMET并不意味着多部分响应。

  2. COMET表示:传统的单部分响应,但保持(具有无限循环和休眠),直到有可用数据。所以浏览器对每个动作都有1个请求/响应(在最坏的情况下),而不是每x秒一个请求,即使没有任何响应值发生。

答案 1 :(得分:4)

您提到希望在没有数据库的情况下工作,并且没有客户端轮询服务器以进行更新。

理论上你可以通过将聊天的“日志”存储在服务器上的文本文件中,然后更改页面以便用户在chat.php页面上执行GET请求来实现这一点,但PHP页面实际上从未实际完成发回给用户。 (例如,响应从未完成)

你需要发回一些“ no op ”数据,以便在没有消息的情况下保持连接,但理论上这可行。

问题是,要完成上述工作仍有很多工作要做。您需要将AJAX帖子发送回服务器以提交新评论...用户的浏览器将一直旋转(除非您将聊天日志嵌套在iframe中 - 例如更多工作)......以及这种类型设置将很难管理。

我建议从其他地方抓一个免费的聊天脚本(例如http://tinychat.com/),或者如果你想自己动手(为了好玩/体验),那么请继续,但是从数据库开始并构建一个页面,将从服务器推送和拉取消息。

最后,如果您担心使用AJAX请求“锤击”服务器......请不要。只需构建聊天,然后如果发现存在性能问题,请返回StackOverflow,询问如何优化它,以便在没有活动时数百个请求不会充斥聊天。

答案 2 :(得分:2)

虽然不是为了轻松推送而使用HTTP,但您可以通过让PHP脚本永远不会终止并仔细观察JavaScript结果来模拟推送连接。

基本上你是在模拟一个流阅读器。

答案 3 :(得分:1)

如果您希望新用户加载在他们进入房间之前发生的聊天记录,则需要数据库或其他存储空间。除非你试图创建一个学习聊天,否则有太多的东西可以免费使用。

http://tinychat.com是另一个简单的聊天网站。

AJAX工作正常。我为我的一个网站创建了一个简单的页面。但我发现聊天不会像你想象的那样频繁使用。

通过托管IRC服务器并允许用户使用具有数据交换功能的IRC客户端,共享数据变得更加复杂并且更容易实现。虽然没有什么能阻止你让一个用户上传到网站,但其他人下载了。使用Web界面时,人与人之间会很困难,因为用户之间没有任何关联。

答案 4 :(得分:1)

  

并立即显示在每个人的浏览器上

使用php / JS,您无法将数据从服务器推送到客户端。因此,您的客户需要从服务器请求数据。这就是scunliffe在他的帖子中描述的内容。

答案 5 :(得分:1)

您可以使用像PubNub这样的服务完全使用HTML和Javascript完成此操作。您不需要数据库,因为您可以使用history api之类的内容来填充最后的x个聊天消息。

以下是使用PubNub构建聊天应用的快速教程。

10行代码中的实时聊天应用

enter image description here

Enter Chat and press enter
<div><input id=input placeholder=you-chat-here /></div>

Chat Output
<div id=box></div>

<script src=http://cdn.pubnub.com/pubnub.min.js></script>
<script>(function(){
var box = PUBNUB.$('box'), input = PUBNUB.$('input'), channel = 'chat';
PUBNUB.subscribe({
    channel  : channel,
    callback : function(text) { box.innerHTML = (''+text).replace( /[<>]/g, '' ) + '<br>' + box.innerHTML }
});
PUBNUB.bind( 'keyup', input, function(e) {
    (e.keyCode || e.charCode) === 13 && PUBNUB.publish({
        channel : channel, message : input.value, x : (input.value='')
    })
} )
})()</script>