【问题标题】:How to implement a chat room using Jquery/PHP?如何使用 Jquery/PHP 实现聊天室?
【发布时间】:2011-05-09 15:21:05
【问题描述】:

我希望使用 PHP/Javascript (Jquery) 实现一个聊天室,同时具有群聊和私人聊天功能。

问题在于如何以自然的方式不断更新界面,以及如何在私人聊天中显示“X 正在输入..”消息。

显而易见的方法似乎是每 X 秒/毫秒 javascript 对服务器进行一次 ping 操作,并在上次 ping 和现在之间获取新消息列表。但是,如果聊天室突然充斥着 5 条消息,这会使界面看起来有点不自然。我宁愿每条消息都按键入时显示。

有没有办法让 javascript 保持与服务器的持续连接,服务器将任何新消息推送到此连接,然后 javascript 将它们添加到界面中,以便它们同时出现,几乎在服务器接收到它们的同时出现?

我知道有一些轮询选项需要您安装一些 apache 模块等,但我对系统管理员很差劲,因此我希望在共享主机帐户上有一个非常容易安装的解决方案,或仅 php/mysql 的解决方案。

【问题讨论】:

  • PHP in CLI=Yes, PHP in HTTP call=No, PHP + Javascript=Possible cause JavaScript can fire multi requests
  • @Ajreal - 如果你能发布一些示例代码来展示它是如何完成的,将不胜感激
  • 我今天确实在看这个:css-tricks.com/chat2 它不会自动更新,但它确实为 PHP/jQuery 聊天室提供了背景。祝你好运!

标签: php javascript jquery ajax ajax-polling


【解决方案1】:

我以前没有用 PHP 做过,但你最好打赌可能是某种套接字连接。这是用于套接字的PHP manual

我不记得是谁的教程,但我创建了一个聊天室,就像您想要的那样,客户端使用 Flash,服务器使用 Java。我认为this link 可能是教程所在的位置,它可能会对您有所帮助。

【讨论】:

  • 我认为套接字对此没有多大用处。套接字必须连接到某些东西,即用户必须在他们的计算机中拥有允许连接的东西
  • 你是什么意思?当我使用 Flash 时,它可以嵌入到浏览器中,而且效果很好。
  • @Aaron Hathaway:flash 不是网页(文本、HTML),是二进制程序
  • @ajreal:嗯,我不记得说过 Flash 是网页?它嵌入在网页上的 HTML 中。
  • 也许套接字可以连接到javascript?
【解决方案2】:

你看过PHPDaemon,它是通过积极使用libevent和pnctl编写的吗? It 有很多功能,甚至是简单的chat 演示应用程序。甚至它也有一些生产实现。

【讨论】:

  • 这很有趣,它似乎可以完成工作。但它可以安装在共享主机上吗?我从文档中不清楚我需要在哪里上传代码才能使用 SSH 运行安装命令(我假设)
  • PHPDeamon 是一个后端服务器解决方案,因此对于共享主机帐户来说不是一个好的解决方案。
【解决方案3】:

我建议你试试Socket.IONodeJS。 Socket.IO 为您提供了一个很好且非常简单的客户端 API,适用于大多数现代浏览器并尽可能使用适当的传输(Websocket、长轮询等)。 NodeJS 是一个服务器端守护进程,它拥有 HTTP 连接。 Socket.IO 的官方网站包含有关如何一起使用它们的信息。希望对你有帮助。

【讨论】:

  • NodeJS 需要 Python 2.4 或更高版本,而不是 PHP
【解决方案4】:

我相信您正在查看的问题需要使用 Comet 网络编程。您可以通过搜索 Comet 编程和 Ajaxian 找到更多关于 wikipedia 的详细信息(我还是这个网站的新手,我不能在回复中发布超过 1 个链接)。

问题在于,这在服务器端使用 php 无法轻松实现。更多细节: using comet with php

另外,如果你在谷歌上搜索“php comet”,你会找到一个教程来达到预期的效果。

稍后编辑

Ape project

使用此引擎实施了一个项目。很棒。

Comet with php

希望这会有所帮助, 加布里埃尔

【讨论】:

  • 我一直在研究 APE,它似乎存在一些令人讨厌的问题,尽管它被认为是“稳定的”。见:nulldevice.de/2010/09/ape-ajax-push-engine
  • 感谢您的提醒和链接。我也遇到过一些这样的问题。
【解决方案5】:

这可能是一个很好的起点

http://css-tricks.com/jquery-php-chat/

【讨论】:

    【解决方案6】:

    使用 PHP/AJAX/JSON 聊天

    我使用这本书/教程来编写我的聊天应用程序:

    AJAX and PHP: Building Responsive Web Applications: Chapter 5: AJAX chat and JSON

    它展示了如何从头开始编写一个完整的聊天脚本。


    基于彗星的聊天

    您还可以将CometPHP 一起使用。

    发件人:zeitoun

    Comet 使 Web 服务器无需客户端请求即可将数据发送到客户端。因此,这种技术将产生比经典 AJAX 更具响应性的应用程序。在经典的 AJAX 应用程序中,无法实时通知 Web 浏览器(客户端)服务器数据模型已更改。用户必须创建一个请求(例如通过单击一个链接)或一个周期性的 AJAX 请求必须发生,以便从服务器获取新数据。

    我将向您展示两种使用 PHP 实现 Comet 的方法。例如:

    1. 基于隐藏的<iframe> 使用服务器时间戳
    2. 基于经典的 AJAX 不返回请求

    第一个在客户端上实时显示服务器日期,显示一个迷你聊天。

    方法一:iframe + 服务器时间戳

    你需要:

    • 一个后端PHP脚本来处理持久的http请求backend.php
    • 前端 HTML 脚本加载 Javascript 代码index.html
    • prototype JS library,不过你也可以用jQuery

    后端脚本 (backend.php) 将无限循环,只要客户端连接,就会返回服务器时间。

    <?php
    header("Cache-Control: no-cache, must-revalidate");
    header("Expires: Sun, 5 Mar 2012 05:00:00 GMT");
    flush();
    ?>
    
    <!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">
    
    <head>
        <title>Comet php backend</title>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    </head>
    
    <body>
    <script type="text/javascript">
    // KHTML browser don't share javascripts between iframes
    var is_khtml = navigator.appName.match("Konqueror") || navigator.appVersion.match("KHTML");
    if (is_khtml)
    {
      var prototypejs = document.createElement('script');
      prototypejs.setAttribute('type','text/javascript');
      prototypejs.setAttribute('src','prototype.js');
      var head = document.getElementsByTagName('head');
      head[0].appendChild(prototypejs);
    }
    // load the comet object
    var comet = window.parent.comet;
    </script>
    
    <?php
    while(1) {
        echo '<script type="text/javascript">';
        echo 'comet.printServerTime('.time().');';
        echo '</script>';
        flush(); // used to send the echoed data to the client
        sleep(1); // a little break to unload the server CPU
    }
    ?>
    </body>
    </html>
    

    前端脚本 (index.html) 创建一个“comet”javascript 对象,它将后端脚本连接到时间容器标签。

    <!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">
    <head>
      <title>Comet demo</title>
      <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
      <script type="text/javascript" src="prototype.js"></script>
    
    </head>
    <body>
      <div id="content">The server time will be shown here</div>
    
    <script type="text/javascript">
    var comet = {
    connection   : false,
    iframediv    : false,
    
    initialize: function() {
      if (navigator.appVersion.indexOf("MSIE") != -1) {
    
        // For IE browsers
        comet.connection = new ActiveXObject("htmlfile");
        comet.connection.open();
        comet.connection.write("<html>");
        comet.connection.write("<script>document.domain = '"+document.domain+"'");
        comet.connection.write("</html>");
        comet.connection.close();
        comet.iframediv = comet.connection.createElement("div");
        comet.connection.appendChild(comet.iframediv);
        comet.connection.parentWindow.comet = comet;
        comet.iframediv.innerHTML = "<iframe id='comet_iframe' src='./backend.php'></iframe>";
    
      } else if (navigator.appVersion.indexOf("KHTML") != -1) {
    
        // for KHTML browsers
        comet.connection = document.createElement('iframe');
        comet.connection.setAttribute('id',     'comet_iframe');
        comet.connection.setAttribute('src',    './backend.php');
        with (comet.connection.style) {
          position   = "absolute";
          left       = top   = "-100px";
          height     = width = "1px";
          visibility = "hidden";
        }
        document.body.appendChild(comet.connection);
    
      } else {
    
        // For other browser (Firefox...)
        comet.connection = document.createElement('iframe');
        comet.connection.setAttribute('id',     'comet_iframe');
        with (comet.connection.style) {
          left       = top   = "-100px";
          height     = width = "1px";
          visibility = "hidden";
          display    = 'none';
        }
        comet.iframediv = document.createElement('iframe');
        comet.iframediv.setAttribute('src', './backend.php');
        comet.connection.appendChild(comet.iframediv);
        document.body.appendChild(comet.connection);
    
      }
    },
    
    // this function will be called from backend.php  
    printServerTime: function (time) {
      $('content').innerHTML = time;
    },
    
    onUnload: function() {
      if (comet.connection) {
        comet.connection = false; // release the iframe to prevent problems with IE when reloading the page
      }
    }
    }
    Event.observe(window, "load",   comet.initialize);
    Event.observe(window, "unload", comet.onUnload);
    
    </script>
    
    </body>
    </html>
    

    方法二:AJAX不返回请求

    您需要与方法1中的相同+一个用于数据交换的文件(data.txt

    现在,backend.php 将做两件事:

    1. 发送新消息时写入“data.txt”
    2. 只要“data.txt”文件不变就无限循环
    <?php
    $filename  = dirname(__FILE__).'/data.txt';
    
    // store new message in the file
    $msg = isset($_GET['msg']) ? $_GET['msg'] : '';
    if ($msg != '')
    {
        file_put_contents($filename,$msg);
        die();
    }
    
    // infinite loop until the data file is not modified
    $lastmodif    = isset($_GET['timestamp']) ? $_GET['timestamp'] : 0;
    $currentmodif = filemtime($filename);
    while ($currentmodif <= $lastmodif) // check if the data file has been modified
    {
        usleep(10000); // sleep 10ms to unload the CPU
        clearstatcache();
        $currentmodif = filemtime($filename);
    }
    
    // return a json array
    $response = array();
    $response['msg']       = file_get_contents($filename);
    $response['timestamp'] = $currentmodif;
    echo json_encode($response);
    flush();
    ?>
    

    前端脚本(index.html)创建&lt;div id="content"&gt;&lt;/div&gt;标签,其中包含来自“data.txt”文件的聊天消息,最后它创建一个“comet”javascript对象,该对象将按顺序调用后端脚本以查看新的聊天消息。

    comet 对象将在每次收到新消息和每次发布新消息时发送 AJAX 请求。持久连接仅用于监视新消息。时间戳 url 参数用于标识最后请求的消息,以便服务器仅在“data.txt”时间戳比客户端时间戳更新时返回。

    <!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">
    <head>
      <title>Comet demo</title>
      <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
      <script type="text/javascript" src="prototype.js"></script>
    </head>
    <body>
    
    <div id="content">
    </div>
    
    <p>
    <form action="" method="get" onsubmit="comet.doRequest($('word').value);$('word').value='';return false;">
      <input type="text" name="word" id="word" value="" />
      <input type="submit" name="submit" value="Send" />
    </form>
    </p>
    
    <script type="text/javascript">
    var Comet = Class.create();
    Comet.prototype = {
    
    timestamp: 0,
    url: './backend.php',
    noerror: true,
    
    initialize: function() { },
    
    connect: function()
    {
      this.ajax = new Ajax.Request(this.url, {
        method: 'get',
        parameters: { 'timestamp' : this.timestamp },
        onSuccess: function(transport) {
          // handle the server response
          var response = transport.responseText.evalJSON();
          this.comet.timestamp = response['timestamp'];
          this.comet.handleResponse(response);
          this.comet.noerror = true;
        },
        onComplete: function(transport) {
          // send a new ajax request when this request is finished
          if (!this.comet.noerror)
            // if a connection problem occurs, try to reconnect each 5 seconds
            setTimeout(function(){ comet.connect() }, 5000); 
          else
            this.comet.connect();
          this.comet.noerror = false;
        }
      });
      this.ajax.comet = this;
    },
    
    disconnect: function()
    {
    },
    
    handleResponse: function(response)
    {
      $('content').innerHTML += '<div>' + response['msg'] + '</div>';
    },
    
    doRequest: function(request)
    {
      new Ajax.Request(this.url, {
        method: 'get',
        parameters: { 'msg' : request 
      });
    }
    }
    var comet = new Comet();
    comet.connect();
    </script>
    
    </body>
    </html>
    

    或者

    您还可以查看其他聊天应用程序,看看他们是如何做到的:

    【讨论】:

    • 谢谢 - 我已经尝试过这段代码,但是使用 Iframe 方法,如果我使用 flush(),在谷歌浏览器中我不会立即看到响应,只有在页面完成加载时?
    • 您需要保持连接处于活动状态。第二种方法使用“长轮询”。另见 cmets:zeitoun.net/articles/comet_and_php/start.
    • 我刚找到Ajax Chat;一个使用 ajax、sockets、php 和 ruby​​ 的开源网络聊天应用程序(最后一个是可选的):blueimp.net/ajax
    • I'd prefer if there was a very easy to install solution on a shared hosting account, or a php/mysql only solution.,建议您使用推送服务,让聊天环境更加美好。 (通过推送,您的客户端不必请求服务器获取新数据 + 它使聊天成为实时。)一些具有良好文档和库的推送服务:beaconpush.compusherapp.comkwwika.com
    • 如果我希望能够保持多个聊天会话,如何实现data.txt文件?
    【解决方案7】:

    我建议使用 HTML5 WebSockets 来实现它,使用长轮询或彗星作为旧浏览器的后备。 WebSockets 打开一个到浏览器的持久连接。 有一个开源的php implementation of a websocket server

    【讨论】:

      【解决方案8】:

      轮询不是一个好主意。您需要一个使用长轮询或网络套接字的解决方案。

      http://hookbox.org 可能是您可以使用的最佳工具。

      它是一个存在于服务器和浏览器之间的盒子,它管理称为通道的抽象(想想 IRC 通道)。它在 github 上是开源的:https://github.com/hookbox/hookbox 该盒子是用 Python 编写的,但它可以很容易地与用任何语言编写的服务器一起使用。它还附带一个基于 jsio 构建的 Javascript 库(使用 websockets、长轮询或任何浏览器上可用的最佳技术),以保证它使用浏览器中可用的最佳技术。在演示中,我看到了实时聊天用几行代码实现。

      Hookbox 的目的是简化实时 Web 应用程序的开发,重点是与现有 Web 技术的紧密集成。简单地说,Hookbox 是一个支持 Web 的消息队列。浏览器可以直接连接到 Hookbox,订阅指定频道,并在这些频道上实时发布和接收消息。外部应用程序(通常是 Web 应用程序本身)也可以通过 Hookbox REST 接口将消息发布到通道。所有身份验证和授权均由外部 Web 应用程序通过指定的“webhook”回调执行。

      每当用户连接或操作频道时,(订阅、发布、取消订阅)Hookbox 都会向 Web 应用程序发出 http 请求以授权操作。订阅频道后,用户的浏览器将通过 javascript api 接收来自另一个浏览器的实时事件,或通过 REST api 来自 Web 应用程序的实时事件。

      他们的关键见解是,所有使用 hookbox 的应用程序开发要么使用 javascript,要么使用 Web 应用程序本身的本地语言(例如 PHP)。

      您需要一个可以运行 Python 但您不必了解 Python 的服务器。

      如果您只想使用 websockets 和 PHP,这是一个很好的起点:http://blancer.com/tutorials/69066/start-using-html5-websockets-today/

      【讨论】:

        【解决方案9】:

        我知道这已经很晚了,但是here

        编辑:更新链接

        【讨论】:

          【解决方案10】:

          这看起来很有希望!甚至可能超级容易重新设计 :)

          http://www.php-development.ru/javascripts/ajax-chat.php

          Javascript/PHP 中的 Ajax 聊天脚本

          说明

          Ajax Chat 是用 JavaScript 和 PHP 实现的轻量级可定制网络聊天软件。该脚本不需要 Java、Flash 或任何其他插件。

          特点

          • 公共和私人聊天。
          • 以注册用户或访客身份登录。
          • 离开状态、自定义颜色、笑脸、用户性别/状态图标。
          • Ajax Chat 可以通过实现用户身份验证例程与第三方会员系统集成。高级集成选项:如果用户登录网站,他可以自动登录聊天。

          *请注意这是来自the original site的复制/粘贴。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-12-26
            相关资源
            最近更新 更多