Socket.IO - 快速指南


Socket.IO - 概述

Socket.IO 是一个用于实时 Web 应用程序的 JavaScript 库。它支持 Web 客户端和服务器之间的实时、双向通信。它有两部分:一个在浏览器中运行的客户端库和一个用于 Node.js 的服务器端库。两个组件都有相同的 API。

实时应用

实时应用程序 (RTA) 是在用户感知为即时或当前的一段时间内运行的应用程序。

实时应用程序的一些示例是 -

  • 即时消息- 聊天应用程序,如 Whatsapp、Facebook Messenger 等。您无需刷新应用程序/网站即可接收新消息。

  • 推送通知- 当有人在 Facebook 上的图片中标记您时,您会立即收到通知。

  • 协作应用程序- 像 google docs 这样的应用程序,允许多人同时更新相同的文档并将更改应用于所有人的实例。

  • 在线游戏- 诸如《反恐精英》、《使命召唤》等游戏也是实时应用程序的一些示例。

为什么选择Socket.IO?

使用 LAMP (PHP) 等流行的 Web 应用程序堆栈编写实时应用程序传统上非常困难。它涉及轮询服务器以了解更改,跟踪时间戳,并且它比应有的速度要慢得多。

传统上,套接字是大多数实时系统构建的解决方案,在客户端和服务器之间提供双向通信通道。这意味着服务器可以向客户端推送消息。每当事件发生时,服务器都会获取该事件并将其推送到相关的连接客户端。

Socket.IO 非常流行, Microsoft Office、Yammer、Zendesk、Trello 等都使用它。和许多其他组织构建强大的实时系统。它是GitHub上最强大的JavaScript 框架之一,也是最依赖的 NPM(节点包管理器)模块。Socket.IO 还拥有庞大的社区,这意味着寻求帮助非常容易。

ExpressJS

我们将使用 Express 构建 Socket.IO 将使用的 Web 服务器。任何其他节点服务器端框架甚至节点 HTTP 服务器都可以使用。然而,ExpressJS 可以轻松定义路由和其他内容。要了解有关 Express 的更多信息并了解它的基本概念,请前往 – ExpressJS 教程。

Socket.IO - 环境

要开始使用Socket.IO进行开发,您需要安装Nodenpm(节点包管理器)。如果您没有这些,请转到节点设置以在本地系统上安装节点。通过在终端中运行以下命令来确认已安装 Node 和 npm。

node --version
npm --version

您应该得到类似于以下内容的输出 -

v14.17.0

6.14.13打开终端并在终端中输入以下内容以创建新文件夹并输入以下命令 -

$ mkdir test-project
$ cd test-proect
$ npm init

它会问你一些问题;按以下方式回答它们 -

环境设置

这将创建一个“package.json node.js”配置文件。现在我们需要安装ExpressSocket.IO。要安装它们并将它们保存到package.json 文件,请在终端中的项目目录中输入以下命令 -

npm install --save express socket.io

最后一件事是我们应该不断重新启动服务器。当我们进行更改时,我们将需要一个名为nodemon的工具要安装 nodemon,请打开终端并输入以下命令 -

npm install -g nodemon

每当您需要启动服务器时,请使用nodemon app.js,而不是使用node app.js。这将确保您在更改文件时无需重新启动服务器。它加快了开发过程。

现在,我们的开发环境已经搭建完毕。现在让我们开始使用 Socket.IO 开发实时应用程序。

Socket.IO - 你好世界

在下一章中,我们将讨论使用 Socket.IO 库和 ExpressJS 的基本示例。

例子

首先,创建一个名为app.js的文件并输入以下代码来设置 Express 应用程序 -

var app = require('express')();
var http = require('http').Server(app);

app.get('/', function(req, res){
   res.sendFile('E:/test/index.html');
});

http.listen(3000, function(){
   console.log('listening on *:3000');
});

我们需要一个index.html文件来提供服务,创建一个名为index.html的新文件并在其中输入以下代码 -

<!DOCTYPE html>
<html>
   <head><title>Hello world</title></head>
   <body>Hello world</body>
</html>

要测试这是否有效,请转到终端并使用以下命令运行此应用程序 -

nodemon app.js

这将在 localhost:3000 上运行服务器。转到浏览器并输入 localhost:3000 进行检查。如果一切顺利,页面上会打印一条消息“Hello World” 。

以下是另一个示例(这需要 Socket.IO),每次用户访问此页面时,它都会记录“用户已连接”,而每次有人离开/关闭此页面时,它都会记录“用户已断开连接”。

var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);

app.get('/', function(req, res){ res.sendFile('E:/test/index.html');
});

//Whenever someone connects this gets executed
io.on('connection', function(socket){
   console.log('A user connected');
   
   //Whenever someone disconnects this piece of code executed
   socket.on('disconnect', function () {
      console.log('A user disconnected');
   });
});
http.listen(3000, function(){
   console.log('listening on *:3000');
});

require('socket.io')(http) 创建一个附加到 http 服务器的新的 socket.io 实例。io.on 事件处理程序使用套接字对象处理其中的连接、断开等事件。

我们已经设置了服务器来记录连接和断开连接的消息。我们现在必须包含客户端脚本并在那里初始化套接字对象,以便客户端可以在需要时建立连接。该脚本由位于“/socket.io/socket.io.js”的 io 服务器提供服务

完成上述过程后,index.html 文件将如下所示 -

<!DOCTYPE html>
<html>
   <head><title>Hello world</title></head>
   <script src="/socket.io/socket.io.js"></script>
   <script>
      var socket = io();
   </script>
   <body>Hello world</body>
</html>

如果您现在访问 localhost:3000(确保您的服务器正在运行),您将在浏览器中看到Hello World打印。现在检查您的服务器控制台日志,它将显示以下消息 -

A user connected

如果刷新浏览器,它将断开套接字连接并重新创建。您可以在控制台日志中看到以下内容 -

A user connected
A user disconnected
A user connected

Socket.IO - 事件处理

套接字基于事件工作。有一些保留的事件,可以使用服务器端的套接字对象来访问。

这些是 -

  • 连接
  • 信息
  • 断开
  • 重新连接
  • 加入并
  • 离开。

客户端套接字对象还为我们提供了一些保留事件,它们是 -

  • 连接
  • 连接错误
  • 连接超时
  • 重新连接等

现在,让我们看一个使用 SocketIO 库处理事件的示例。

实施例1

In the Hello World example, we used the connection and disconnection events to
log when a user connected and left. Now we will be using the message event to
pass message from the server to the client. To do this, modify the io.on
('connection', function(socket)) as shown below –var app =
require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);

app.get('/', function(req, res){
   res.sendFile('E:/test/index.html');
});
 
io.on('connection', function(socket){
   console.log('A user connected');
 
   // Send a message after a timeout of 4seconds
   setTimeout(function(){
      socket.send('Sent a message 4seconds after connection!');
   }, 4000);
   socket.on('disconnect', function () {
      console.log('A user disconnected');
   });
});
http.listen(3000, function(){
   console.log('listening on *:3000');
});

这将在客户端连接后四秒向我们的客户端发送一个名为message(built in)的事件。套接字对象上的发送函数关联“消息”事件。

现在,我们需要在客户端处理此事件,为此,请将 index.html 页面的内容替换为以下内容 -

<!DOCTYPE html>
<html>
   <head><title>Hello world</title></head>
   <script src="/socket.io/socket.io.js"></script>
   <script>
      var socket = io();
      socket.on('message', function(data){document.write(data)});
   </script>
   <body>Hello world</body>
</html>

我们现在正在客户端处理“消息”事件。现在,当您在浏览器中转到该页面时,您将看到以下屏幕截图。

之前的活动

4 秒过去后,服务器发送消息事件,我们的客户端将处理它并产生以下输出 -

之后的活动

注意- 我们在此处发送了一串文本;在任何情况下我们都可以发送一个对象。

Message 是 API 提供的内置事件,但在实际应用程序中没有多大用处,因为我们需要能够区分事件。

为了实现这一点,Socket.IO 为我们提供了创建自定义事件的能力。您可以使用socket.emit函数创建和触发自定义事件。以下代码发出一个名为testerEvent的事件-

var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);

app.get('/', function(req, res){
   res.sendFile('E:/test/index.html');
});
   
io.on('connection', function(socket){
   console.log('A user connected');
   // Send a message when
   setTimeout(function(){
      // Sending an object when emmiting an event
      socket.emit('testerEvent', { description: 'A custom event named testerEvent!'});
   }, 4000);
   socket.on('disconnect', function () {
      console.log('A user disconnected');
   });
});
http.listen(3000, function(){
   console.log('listening on localhost:3000');
});

为了在客户端处理这个自定义事件,我们需要一个监听事件 testerEvent 的监听器。以下代码在客户端处理此事件 -

<!DOCTYPE html>
<html>
   <head><title>Hello world</title></head>
   <script src="/socket.io/socket.io.js"></script>
   <script>
      var socket = io();
      socket.on('testerEvent', function(data){document.write(data.description)});
   </script>
   <body>Hello world</body>
</html>

这将与我们之前的示例以相同的方式工作,在本例中事件是 testerEvent。当您打开浏览器并转到 localhost:3000 时,您会看到 -

Hello world

四秒后,该事件将被触发,浏览器将把文本更改为 -

A custom event named testerEvent!

实施例2

我们还可以从客户端发出事件。要从客户端发出事件,请在套接字对象上使用发出函数。

<!DOCTYPE html>
<html>
   <head><title>Hello world</title></head>
   <script src="/socket.io/socket.io.js"></script>
   <script>
      var socket = io();
      socket.emit('clientEvent', 'Sent an event from the client!');
   </script>
   <body>Hello world</body>
</html>

要处理这些事件,请对服务器上的套接字对象使用on 函数。

var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);

app.get('/', function(req, res){
   res.sendFile('E:/test/index.html');
});
io.on('connection', function(socket){
   socket.on('clientEvent', function(data){
      console.log(data);
   });
});

http.listen(3000, function(){
   console.log('listening on localhost:3000');
});

因此,现在如果我们访问 localhost:3000,我们将触发一个名为clientEvent的自定义事件。该事件将通过日志记录在服务器上处理 -

Sent an event from the client!

Socket.IO - 广播

广播意味着向所有连接的客户端发送消息。广播可以在多个级别上进行。我们可以将消息发送给所有连接的客户端、命名空间上的客户端以及特定房间中的客户端。要将事件广播给所有客户端,我们可以使用io.sockets.emit方法。

注意- 这将向所有连接的客户端发出事件(事件可能触发此事件的套接字)。

在此示例中,我们将向所有用户广播连接的客户端数量。更新app.js文件以包含以下内容 -

var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);

app.get('/', function(req, res){
   res.sendFile('E:/test/index.html');
});
   
var clients = 0;

io.on('connection', function(socket){
   clients++;
   io.sockets.emit('broadcast',{ description: clients + ' clients connected!'});
   socket.on('disconnect', function () {
      clients--;
      io.sockets.emit('broadcast',{ description: clients + ' clients connected!'});
   });
});

http.listen(3000, function(){
   console.log('listening on localhost:3000');
});

在客户端,我们只需要处理广播事件 -

<!DOCTYPE html>
<html>
   <head><title>Hello world</title></head>
   <script src="/socket.io/socket.io.js"></script>
   <script>
      var socket = io();
      socket.on('broadcast',function(data){
         document.body.innerHTML = '';
         document.write(data.description);
      });
   </script>
   <body>Hello world</body>
</html>

如果连接四个客户端,您将得到以下结果 -

全部广播

这是为了向大家发送一个事件。现在,如果我们想向每个人发送一个事件,但不包括引起该事件的客户端(在前面的示例中,它是由连接时的新客户端引起的),我们可以使用 socket.broadcast.emit

让我们向新用户发送一条欢迎消息,并向其他客户通报他/她的加入情况。因此,在您的 app.js 文件中,在客户端连接时向他发送一条欢迎消息并向所有其他人广播连接的客户端号码。

var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);

app.get('/', function(req, res){
   res.sendFile('E:/test/index.html');
});
var clients = 0;

io.on('connection', function(socket){
   clients++;
   socket.emit('newclientconnect',{ description: 'Hey, welcome!'});
   socket.broadcast.emit('newclientconnect',{ description: clients + ' clients connected!'})
   socket.on('disconnect', function () {
      clients--;
      socket.broadcast.emit('newclientconnect',{ description: clients + ' clients connected!'})
   });
});
http.listen(3000, function(){
   console.log('listening on localhost:3000');
});

和你的 html 来处理这个事件 -

<!DOCTYPE html>
<html>
   <head><title>Hello world</title></head>
   <script src="/socket.io/socket.io.js"></script>
   <script>
      var socket = io();
      socket.on('newclientconnect',function(data){
               document.body.innerHTML = '';
               document.write(data.description);
      });
   </script>
   <body>Hello world</body>
</html>

现在,最新的客户端会收到一条欢迎消息,其他客户端会收到当前连接到服务器的客户端数量。

Socket.IO - 命名空间

Socket.IO 允许您为套接字“命名空间”,这本质上意味着分配不同的端点或路径。这是一个有用的功能,可以最大限度地减少资源(TCP 连接)的数量,同时通过引入通信通道之间的分离来分离应用程序中的关注点。多个命名空间实际上共享相同的 WebSockets 连接,从而节省了服务器上的套接字端口。

命名空间是在服务器端创建的。但是,客户端通过向服务器发送请求来加入它们。

默认命名空间

根命名空间“/”是默认命名空间,如果客户端在连接服务器时未指定命名空间,则客户端会加入该命名空间。使用套接字对象客户端与服务器的所有连接都建立到默认名称空间。例如 -

var socket = io();

这会将客户端连接到默认命名空间。此命名空间连接上的所有事件都将由服务器上的io 对象处理。前面的所有示例都利用默认名称空间与服务器进行通信并返回。

自定义命名空间

我们可以创建自己的自定义命名空间。要设置自定义命名空间,我们可以在服务器端调用“of”函数 -

var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);

app.get('/', function(req, res){
   res.sendFile('E:/test/index.html');});
   
var nsp = io.of('/my-namespace');
nsp.on('connection', function(socket){
   console.log('someone connected');
   nsp.emit('hi', 'Hello everyone!');
});
http.listen(3000, function(){
   console.log('listening on localhost:3000');
});

现在,要将客户端连接到此命名空间,您需要将命名空间作为参数提供给io 构造函数调用,以在客户端创建连接和套接字对象。

例如,要连接到上述命名空间,请使用以下 HTML -

<!DOCTYPE html>
<html>
   <head><title>Hello world</title></head>
   <script src="/socket.io/socket.io.js"></script>
   <script>
      var socket = io('/my-namespace');
      socket.on('hi',function(data){
         document.body.innerHTML = '';
         document.write(data);
      });
   </script>
   <body></body>
 </html>

每次有人连接到此命名空间时,他们都会收到一个“hi”事件,显示消息“大家好!”

Socket.IO - 房间

在每个命名空间中,您还可以定义套接字可以加入和离开的任意通道。这些通道称为房间。房间用于进一步分离关注点。房间也像命名空间一样共享相同的套接字连接。使用房间时要记住的一件事是它们只能在服务器端加入。

加入房间

您可以调用套接字上的join方法来将套接字订阅给定的频道/房间。例如,让我们创建名为“room-<room-number>”的房间并加入一些客户端。一旦这个房间已满,就创建另一个房间并在那里加入客户。

注意- 我们目前正在默认名称空间(即“/”)上执行此操作。您还可以以相同的方式在自定义命名空间中实现此功能。

var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
app.get('/', function(req, res){
   res.sendfile('index.html');
});
var roomno = 1;
io.on('connection', function(socket){
   socket.join("room-"+roomno);
   //Send this event to everyone in the room.
   io.sockets.in("room-"+roomno).emit('connectToRoom', "You are in room no. "+roomno);
})
http.listen(3000, function(){
   console.log('listening on localhost:3000');
});

只需在客户端处理此connectToRoom事件即可。

<!DOCTYPE html>
<html>
   <head><title>Hello world</title></head>
   <script src="/socket.io/socket.io.js"></script>
   <script>
      var socket = io();
      socket.on('connectToRoom',function(data){
         document.body.innerHTML = '';
         document.write(data);
      });
   </script>
   <body></body>
</html>

现在,如果您连接三个客户端,前两个客户端将收到以下消息 -

You are in room no. 1

离开房间

要离开房间,您需要调用 left 函数,就像在套接字上调用 join 函数一样。

例如 - 要离开房间 ' room-1 ',

socket.leave("room-"+roomno);

Socket.IO - 错误处理

到目前为止,我们一直在本地服务器上工作,这几乎不会给我们带来与连接、超时等相关的错误。然而,在现实生产环境中,处理此类错误至关重要。因此,我们现在将讨论如何在客户端处理连接错误。

客户端 API 为我们提供了以下内置事件 -

  • 连接- 当客户端成功连接时。

  • 连接- 当客户端正在连接过程中时。

  • 断开连接- 当客户端断开连接时。

  • Connect_failed - 当与服务器的连接失败时。

  • 错误- 从服务器发送错误事件。

  • 消息- 当服务器使用发送功能发送消息时。

  • 重新连接- 当重新连接到服务器成功时。

  • 重新连接- 当客户端正在连接过程中时。

  • Reconnect_failed - 当重新连接尝试失败时。

为了处理错误,我们可以使用在客户端上创建的 out-socket 对象来处理这些事件。

例如 – 如果我们的连接失败,我们可以使用以下代码再次连接到服务器 -

socket.on('connect_failed', function() {
   document.write("Sorry, there seems to be an issue with the connection!");
})

Socket.IO - 日志记录和调试

Socket.IO使用了ExpresJS的主要作者开发的一个非常著名的调试模块,称为debug。早期的 Socket.IO 用于将所有内容记录到控制台,这使得调试问题变得非常困难。v1.0 发布后,您可以指定要记录的内容。

服务器端

查看可用信息的最佳方法是使用 * -

DEBUG=* node app.js

这将对服务器控制台上发生的所有情况进行着色并输出。例如,我们可以考虑以下屏幕截图。

记录示例

客户端

将其粘贴到控制台,单击 Enter 并刷新页面。这将再次将与 Socket.io 相关的所有内容输出到您的控制台。

localStorage.debug = '*';

您可以使用以下命令限制输出以获取来自套接字的传入数据的调试信息。

localStorage.debug = 'socket.io-client:socket';

如果您使用第二条语句来记录信息,您可以看到如下屏幕截图所示的结果 -

客户端日志记录

这里有一篇与 socket.io 调试相关的非常好的博客文章

Socket.IO - 内部结构

在本章中,我们将讨论后备、使用 Socket.IO 的连接、事件和消息。

后备措施

Socket.IO 有很多底层传输机制,可以处理由于跨浏览器问题、WebSocket 实现、防火墙、端口阻塞等而产生的各种约束。

尽管 W3C 已经定义了 WebSocket API 的规范,但仍然缺乏实现。Socket.IO为我们提供了fallback机制,可以处理此类问题。如果我们使用本机 API 开发应用程序,我们必须自己实现回退。Socket.IO 按以下顺序涵盖了大量后备方案 -

  • WebSockets
  • FlashSocket
  • XHR 长轮询
  • XHR 多部分流式传输
  • XHR 轮询
  • JSONP 轮询
  • iframe

使用 Socket.IO 连接

Socket.IO 连接从握手开始。这使得握手成为协议的特殊部分。除了握手之外,协议中的所有其他事件和消息都通过套接字传输。

Socket.IO 旨在与 Web 应用程序一起使用,因此假设这些应用程序始终能够使用 HTTP。正是由于这个原因,Socket.IO 握手是使用握手 URI(传递给 connect 方法)上的 POST 请求通过 HTTP 进行的。

事件和消息

WebSocket 原生 API 仅发送消息。Socket.IO 在这些消息之上提供了一个附加层,它允许我们创建事件,并通过分离发送的不同类型的消息再次帮助我们轻松开发应用程序。

本机 API 仅以纯文本形式发送消息。这也由 Socket.IO 负责。它为我们处理数据的序列化和反序列化。

我们有一个官方的网络客户端 API。对于其他客户端,例如本机手机、其他应用程序客户端,我们也可以通过以下步骤使用Socket.IO。

  • 步骤 1 - 需要使用上面讨论的相同连接协议建立连接。

  • 步骤 2 - 消息的格式必须与 Socket.IO 指定的格式相同。这种格式使 Socket.IO 能够确定消息的类型以及消息中发送的数据以及一些对操作有用的元数据。

消息格式是 -

[type] : [id ('+')] : [endpoint] (: [data]

上述命令中的参数解释如下 -

  • Type是一位整数,指定消息的类型。

  • ID是消息 ID,是用于确认的增量整数。

  • 端点是消息要传递到的套接字端点...

  • 数据是要传递到套接字的关联数据。对于消息,它被视为纯文本,对于其他事件,它被视为 JSON。

在下一章中,我们将在 Socket.IO 中编写一个聊天应用程序。

Socket.IO - 聊天应用程序

现在我们已经熟悉了 Socket.IO,让我们编写一个聊天应用程序,我们可以用它在不同的聊天室中聊天。我们将允许用户选择用户名并允许他们使用该用户名进行聊天。首先,让我们设置 HTML 文件来请求用户名 -

<!DOCTYPE html>
<html>
   <head><title>Hello world</title></head>
   <script src="/socket.io/socket.io.js"></script>
   <script>
      var socket = io();
   </script>
   <body>
      <input type="text" name="name" value="" placeholder="Enter your name!">
      <button type="button" name="button">Let me chat!</button>
   </body>
</html>

现在我们已经设置了 HTML 来请求用户名,让我们创建服务器来接受来自客户端的连接。我们将允许人们使用setUsername事件发送他们选择的用户名。如果用户存在,我们将通过userExists事件进行响应,否则使用userSet事件。

var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);

app.get('/', function(req, res){
   res.sendFile('E:/test/index.html');});
users = [];
io.on('connection', function(socket){
   console.log('A user connected');
   socket.on('setUsername', function(data){
      if(users.indexOf(data) > -1){
         users.push(data);
         socket.emit('userSet', {username: data});
      } else {
         socket.emit('userExists', data + ' username is taken! Try some other username.');
     }
   })
});
http.listen(3000, function(){
   console.log('listening on localhost:3000');
});

当人们点击按钮时,我们需要将用户名发送到服务器。如果用户存在,我们会显示错误消息;否则,我们会显示一个消息屏幕 -

<!DOCTYPE html>
<html>
   <head><title>Hello world</title></head>
   <script src="/socket.io/socket.io.js"></script>
   <script>
      var socket = io();
      function setUsername(){
         socket.emit('setUsername', document.getElementById('name').value);
      };
      var user;
      socket.on('userExists', function(data){
         document.getElementById('error-container').innerHTML = data;
      });
      socket.on('userSet', function(data){
         user = data.username;
         document.body.innerHTML = '<input type="text" id="message">\
         <button type="button" name="button" onclick="sendMessage()">Send</button>\
         <div id="message-container"></div>';
      });
      function sendMessage(){
         var msg = document.getElementById('message').value;
         if(msg){
            socket.emit('msg', {message: msg, user: user});
         }
      }
      socket.on('newmsg', function(data){
         if(user){
            document.getElementById('message-container').innerHTML +='<div><b>' + data.user + '</b>: ' + data.message + '</div>'
         }
      })
   </script>
   <body>
      <div id="error-container"></div>
      <input id="name" type="text" name="name" value="" placeholder="Enter your name!">
      <button type="button" name="button" onclick="setUsername()">Let me chat!</button>
      </body>
   </html>

现在,如果您使用相同的用户名连接两个客户端,则会出现错误,如下面的屏幕截图所示 -

聊天名称已被占用

一旦您提供了可接受的用户名,您将进入一个带有消息框和发送消息按钮的屏幕。现在,我们必须处理消息并将其定向到连接的客户端。为此,修改您的 app.js 文件以包含以下更改 -

var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);

app.get('/', function(req, res){
   res.sendFile('E:/test/index.html');});
users = [];
io.on('connection', function(socket){
   console.log('A user connected');
   socket.on('setUsername', function(data){
      console.log(data);
      if(users.indexOf(data) > -1){
         socket.emit('userExists', data + ' username is taken! Try some other username.');
      } else {
         users.push(data);
         socket.emit('userSet', {username: data});
      }
   });
   socket.on('msg', function(data){
      //Send message to everyone
      io.sockets.emit('newmsg', data);
   })
});
http.listen(3000, function(){
   console.log('listening on localhost:3000');
});

现在将任意数量的客户端连接到您的服务器,为他们提供用户名并开始聊天!在下面的示例中,我们连接了两个名为 Ayush 和 Harshit 的客户端,并从两个客户端发送了一些消息 -

聊天示例