Javascript 如何使用 Jquery/PHP 实现聊天室?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4174521/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 11:14:50  来源:igfitidea点击:

How to implement a chat room using Jquery/PHP?

phpjavascriptjqueryajaxajax-polling

提问by Click Upvote

I'm looking to implement a chat room using PHP/Javascript (Jquery) with both group chat and private chat features.

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

The problem is how to continually update the interface in a natural way and possibly also how to show 'X is typing..' messages in private chat.

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

The obvious way seems to be that every X seconds/milliseconds the javascript pings the server and fetches a list of new messages between the last ping and now. However, this can make the interface seem a bit unnatural, if suddenly the chat room is flooded with 5 messages. I would rather each message appear as it is typed.

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

Is there a way for javascript to maintain a continuous connection to the server, the server pushes any new messages to this connection, and javascript adds them to the interface so they appear simultaneously, almost as soon as the server receives them?

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

I know there are some polling options that require you to install some apache modules etc, but I'm pretty bad of a sysadmin, therefore I'd prefer if there was a very easy to install solution on a shared hosting account, or a php/mysql only solution.

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

回答by Wouter Dorgelo

Chat with PHP/AJAX/JSON

与 PHP/AJAX/JSON 聊天

I used this book/tutorial to write my chat application:

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

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

AJAX 和 PHP:构建响应式 Web 应用程序:第 5 章:AJAX 聊天和 JSON

It shows how to write a complete chat script from scratch.

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



Comet based chat

基于彗星的聊天

You can also use Cometwith PHP.

您还可以将CometPHP 结合使用。

From: zeitoun:

来自: zeitoun:

Comet enables web servers to send data to the client without having any need for the client to request it. Therefor, this technique will produce more responsive applications than classic AJAX. In classic AJAX applications, web browser (client) cannot be notified in real time that the server data model has changed. The user must create a request (for example by clicking on a link) or a periodic AJAX request must happen in order to get new data fro the server.

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

I'll show you two ways to implement Comet with PHP. For example:

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

  1. based on hidden <iframe>using server timestamp
  2. based on a classic AJAX non-returning request
  1. 基于<iframe>使用服务器时间戳隐藏
  2. 基于经典的 AJAX 非返回请求

The first shows the server date in real time on the clients, the displays a mini-chat.

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

Method 1: iframe + server timestamp

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

You need:

你需要:

  • a backend PHP script to handle the persistent http request backend.php
  • a frondend HTML script load Javascript code index.html
  • the prototype JS library, but you can also use jQuery
  • 用于处理持久性 http 请求的后端 PHP 脚本 backend.php
  • 一个前端 HTML 脚本加载 Javascript 代码 index.html
  • 原型JS库,但你也可以使用jQuery

The backend script (backend.php) will do an infinite loop and will return the server time as long as the client is connected.

后端脚本 ( 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>

The frontend script (index.html) creates a "comet" javascript object that will connect the backend script to the time container tag.

前端脚本 ( 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>

Method 2: AJAX non-returning request

方法二:AJAX不返回请求

You need the same as in method 1 + a file for dataexchange (data.txt)

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

Now, backend.php will do 2 things:

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

  1. Write into "data.txt" when new messages are sent
  2. Do an infinite loop as long as "data.txt" file is unchanged
  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();
?>
<?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();
?>

The frontend script (index.html) creates the <div id="content"></div>tags hat will contains the chat messages comming from "data.txt" file, and finally it create a "comet" javascript object that will call the backend script in order to watch for new chat messages.

前端脚本 ( index.html) 创建<div id="content"></div>标签 hat 将包含来自“data.txt”文件的聊天消息,最后它创建一个“comet”javascript 对象,该对象将调用后端脚本以观察新的聊天消息。

The comet object will send AJAX requests each time a new message has been received and each time a new message is posted. The persistent connection is only used to watch for new messages. A timestamp url parameter is used to identify the last requested message, so that the server will return only when the "data.txt" timestamp is newer that the client timestamp.

每次收到新消息和每次发布新消息时,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>


Alternatively

或者

You can also have a look at other chat applications to see how they did it:

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

回答by Chris Cinelli

Polling is not a good idea. You need a solution that use long polling or web sockets.

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

http://hookbox.orgis probably the best tool you can use.

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

It is a box that lives between the server and the browsers and manages abstractions called channels (think about an IRC channel). It is open source on github: https://github.com/hookbox/hookboxThe box is written in Python but it can easily be used with a server written in any language. It also come with a Javascript library that is built on jsio (uses websockets, long-polling, or whatever is the best technology available on the browser) that guarantee that it uses the best technology available in the browsers.In a demo I saw a realtime chatimplemented with few line of code.

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

Hookbox's purpose is to ease the development of real-time web applications, with an emphasis on tight integration with existing web technology. Put simply, Hookbox is a web-enabled message queue. Browers may directly connect to Hookbox, subscribe to named channels, and publish and receive messages on those channels in real-time. An external application (typically the web application itself) may also publish messages to channels by means of the Hookbox REST interface. All authentication and authorization is performed by an external web application via designated “webhook” callbacks.

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

alt text

替代文字

Any time a user connects or operates on a channel, ( subscribe, publish, unsubscribe) Hookbox makes an http request to the web application for authorization for the action. Once subscribed to a channel, the user's browser will receive real-time events that originate either in another browser via the javascript api, or from the web application via the REST api.

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

They key insight is that all application development with hookbox Happens either in javascript, or in the native language of the web application itself (e.g. PHP.)

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

You need a server that can run Python BUT you do NOT have to know Python.

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

If instead you want to use just websockets and PHP this is good starting point: http://blancer.com/tutorials/69066/start-using-html5-websockets-today/

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

回答by nefo_x

Have you looked at PHPDaemon, which is written with active usage of libevent and pnctl? Ithas lots of features and even simple chatdemo application. Even it has some production implementations.

您是否看过PHPDaemon,它是通过积极使用 libevent 和 pnctl 编写的?有很多功能,甚至是简单的聊天演示应用程序。即使它有一些生产实现。

回答by Gipsy King

I suggest to implement it with HTML5 WebSockets, with long polling or comet as a fallback for older browsers. WebSockets open a persistent connection to the browser. There is an open source php implementation of a websocket server.

我建议使用 HTML5 WebSockets 实现它,使用长轮询或 Comet 作为旧浏览器的后备。WebSockets 打开与浏览器的持久连接。有一个 websocket 服务器的开源php 实现

回答by Gipsy King

this could be a good starting point

这可能是一个很好的起点

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

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

回答by Gabriel Croitoru

I believe the problem you are looking at requires the use of comet web programming. You can find more details on wikipedia, by searching for Comet programming, and on Ajaxian (I'm still new to this site and I can't post more than 1 link in the response).

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

The problem is that this can't be easily achieved with php on the server side. More details: using comet with php

问题是在服务器端使用 php 无法轻松实现这一点。更多细节: 在 php 中使用 Comet

Also, if you search on google for 'php comet' you'll find a tutorial to achieve the desired effect.

此外,如果您在 google 上搜索 'php comet',您会找到一个教程来实现所需的效果。

LATER EDIT

稍后编辑

Ape project

猿项目

Implemented a project using this engine. Is great.

使用这个引擎实现了一个项目。是很棒的。

Comet with php

彗星与php

Hope this helps, Gabriel

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

回答by Gabriel Croitoru

I know this is very late, but here

我知道这已经很晚了,但在这里

EDIT: Updated link

编辑:更新链接

回答by Qwerty

This looks promising! Might even be super easy to restyle :)

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

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

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

Ajax Chat script in Javascript/PHP

Javascript/PHP 中的 Ajax 聊天脚本

Description

描述

Ajax Chat is a light-weight customizable web chat software implemented in JavaScript and PHP. The script does not require Java, Flash, or any other plugins.

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

Features

特征

  • Public and private chat.
  • Login as a registered user or as a guest.
  • Away status, custom colors, smileys, user gender/status icons.
  • Ajax Chat can be integrated with a third-party membership system by implementing user authentication routine. Advanced integration options: if user is logged in to the website, he can be logged in to the chat automatically.
  • 公共和私人聊天。
  • 以注册用户或访客身份登录。
  • 离开状态、自定义颜色、笑脸、用户性别/状态图标。
  • 通过实现用户身份验证程序,Ajax Chat 可以与第三方会员系统集成。高级集成选项:如果用户登录网站,他可以自动登录聊天。

Ajax lightweight chat script

Ajax 轻量级聊天脚本

*Please note that this is a copy/paste from the original site.

*请注意,这是原始网站的复制/粘贴。

回答by galymzhan

I suggest you to try Socket.IOtogether with NodeJS. Socket.IO gives you a nice and very easy client API, works on most modern browsers and uses appropriate transport where possible (Websocket, long polling, etc). NodeJS is a server-side daemon, which holds HTTP connections. Official site of the Socket.IO contains information on how to use them together. Hope it will help you.

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

回答by Aaron Hathaway

I haven't done it with PHP before but you're best bet would probably be some kind of socket connection. Here's the PHP manualfor sockets.

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

I don't remember who's tutorial it was but I made a chat room like what you want using Flash for the client and Java for the server. I think this linkmight be where the tutorial was and it may help you out.

我不记得是谁的教程,但我制作了一个聊天室,就像你想要的那样,客户端使用 Flash,服务器使用 Java。我认为这个链接可能是教程所在的地方,它可以帮助你。