如何用 PHP 制作聊天室脚本? [关闭]

Posted

技术标签:

【中文标题】如何用 PHP 制作聊天室脚本? [关闭]【英文标题】:How to make a chat room script with PHP? [closed] 【发布时间】:2009-04-21 13:01:47 【问题描述】:

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

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

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

不同用户的会话如何相互共享数据?

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

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

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

【问题讨论】:

问题是用户在使用聊天框坐在您的网页上时实际上并没有连接到任何服务器。所以你需要对推/拉技术做一些研究并做出选择。如果您让用户页面刷新,您需要将文本存储在服务器上的某个位置。如果你想将文本推送出去,你需要以某种方式“知道”有多少用户在聊天屏幕上,并且有办法识别他们并将数据推送到他们的屏幕上。 如果您添加此问题的原因,可能更容易对您的问题给出令人满意的答案:您是否只需要一个聊天系统(可能是现有工具的链接),您想要建立一个聊天系统来学习一点(解释如何构建它更好),你不想使用数据库的原因是什么(这是托管要求还是你觉得数据库不好)? 查看 Yshout 页面的源代码,您将看到指向 yshout.js 的链接。通读应该可以解释它是如何更新页面的。 AJAX 的重点是在向服务器发出请求时不必刷新/重新加载页面。使用“反向 AJAX”可以使用“长轮询”来模拟 HTTP 推送。 【参考方案1】:

(大约)有 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。异步多部分是你想要的:)

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 或原型,所以代码有点肥胖 - 这真的很旧: ))。

这是服务器端部分:

<?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";

?>

更新2

关于数据库:如果您在后端有一个无共享架构,如 mod_php/cgi,您definitley 需要一些 类型的外部存储,如数据库或文本文件。但是:您可以通过编写自己的 http 服务器来依赖内存(可以使用 php,但我不建议将其用于认真的工作)。这并不是很复杂,但可能有点超出您的问题范围^^

更新3

我错了!把一切都搞混了,因为我真的做了很长时间了。以下是更正:

    多部分响应仅适用于 mozilla 浏览器,因此用途有限。 COMET 并不意味着多部分响应。

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

【讨论】:

谢谢!这很有帮助,伙计! +1 好信息。我得到了帮助! 好的,伙计们,这个答案已经超过 3 年了,不再相关了。看看 node.js 和 socket.io。 又一年另一个库:作为 socket.io 的替代品,我会考虑 sock.js。此外,如果您正在处理主要是实时读取而不是实时写入的连接,则可以改用EventSource(又名服务器发送事件)。它有 polyfill 和包装器,但在服务器端,它的行为很像老式的长轮询。您只需像往常一样使用普通的旧 AJAX 进行写入。【参考方案2】:

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

理论上,您可以通过将聊天的“日志”存储在服务器上的文本文件中,并更改您的页面,以便用户在 chat.php 页面上执行 GET 请求,但 PHP 页面实际上从来没有完成发送回用户。 (例如,响应永远不会完成)

当没有消息时,您需要发回一些“no op”数据以保持连接正常,但理论上这是可行的。

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

我建议从其他地方获取一个免费的聊天脚本(例如http://tinychat.com/),或者如果您想推出自己的聊天脚本(为了乐趣/体验)然后继续,但从数据库开始并构建一个可以推送的页面并从服务器拉取消息。

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

【讨论】:

【参考方案3】:

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

本质上,您是在模拟流阅读器。

【讨论】:

这个解决方案的可扩展性如何? 很多聊天都是这样做的(这是我的示例代码所做的)。这不是最好的解决方案,但绝对比拉动更好。【参考方案4】:

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

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

AJAX 工作正常。我为我的一个网站创建了一个简单的页面。但我发现聊天并没有你想象的那么频繁。

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

【讨论】:

继续。这就是我需要在没有数据库的情况下解决的问题:聊天文本如何同步并推送到所有客户端浏览器? 如果没有在注册了“推送”位置的浏览器中作为小程序运行,就无法推送到浏览器。大多数 AJAX 聊天调用一个低开销的页面来请求更新。我在我的身上这样做,提供客户端收到的最后一条消息 id,然后页面响应消息。这需要服务器上的某种类型的存储,即使只是在所有客户端都更新之前的持续时间内。我使用了数据库和过期消息,所以我只会查询大于 id 的未过期消息。【参考方案5】:

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

这里是使用 PubNub 构建聊天应用的快速教程。

10 行代码的实时聊天应用

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>

【讨论】:

谢谢,这是我正在寻找的代码

以上是关于如何用 PHP 制作聊天室脚本? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

如何用gslauncher搭建直播系统

如何为 iPhone 制作聊天客户端 [关闭]

如何用 php 抓取微信文章正文 / 蓝讯

建议实施网络聊天的最佳做法

如何用凌空POST jsonobject

讨论:php 中的高效实时聊天应用程序? [关闭]