『翻译』Socket.IO聊天室程序(官方示例)

官方最新版的示例翻译 阅读原文

开始创建:聊天室程序(Get Started: Chat application)

在这个教程中,我们将会创建一个基本的聊天室程序。它几乎不需要你懂得多少Node.js和Socket.IO的知识,所以,这个教程适用于各个技术水平的开发人员。

介绍(Introduction)

使用LAMP(PHP)这种传统的技术栈去编写一个流行的聊天室程序是很困难的。它包括了服务器的轮询,跟踪时间戳,用它们去做这些会耗费你很多时间。

一直以来,sockets都是即时聊天系统的架构解决方案,它提供一个双向的通讯通道在客户端和服务器之间。

这意味着服务器可以推送消息到客户端。无论你何时发送聊天信息,我们都希望服务器获取到它,并把它推送到其他连接服务器的客户端上。

Web 框架(The web framework)

首先,我们要建立一个简单的HTML页面,负责提交表单和展示消息列表。我们将使用Node.js的web框架express去实现。请确保你安装了Node.js

我们先创建一个package.json来描述我们的项目。我建议你创建一个空文件夹(我把它叫做chat-example)。

1
2
3
4
5
6
{
"name": "socket-chat-example",
"version": "0.0.1",
"description": "my first socket.io app",
"dependencies": {}
}

现在,按顺序把我们所需要的依赖填充到dependencies,我们使用npm install --save

npm install –save express@4.10.2

现在,express已经安装完成,我们创建一个index.js文件,开始搭建我们的程序。

1
2
3
4
5
6
7
8
9
10
var app = require('express')();
var http = require('http').Server(app);
app.get('/', function(req, res){
res.send('<h1>Hello world</h1>');
});
http.listen(3000, function(){
console.log('listening on *:3000');
});

上面这段代码的意思如下:

  1. Express把app初始化为函数处理器(function handler),它提供了一个HTTP服务。

  2. 我们定义一个路由处理器/,当我们进入网站首页时,它会执行。

  3. 我们创建一个http服务去监听3000端口。

如果你运行node index.js,你会看到如下所示:

node-index.js

接下来在浏览器输入http://localhost:3000,你会看到如下所示:

HW

创建HTML(Serving HTML)

到目前为止,index.js只是用res.send返回一个HTML字符串。如果我们把整个程序的HTML代码都放在这,那会使我们头晕眼花,我们再创建一个index.html并启动它。

我们改写路由处理器,用sendFile代替send

1
2
3
app.get('/', function(req, res){
res.sendFile(__dirname + '/index.html');
});

然后在index.html中写入以下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<!doctype html>
<html>
<head>
<title>Socket.IO chat</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font: 13px Helvetica, Arial; }
form { background: #000; padding: 3px; position: fixed; bottom: 0; width: 100%; }
form input { border: 0; padding: 10px; width: 90%; margin-right: .5%; }
form button { width: 9%; background: rgb(130, 224, 255); border: none; padding: 10px; }
#messages { list-style-type: none; margin: 0; padding: 0; }
#messages li { padding: 5px 10px; }
#messages li:nth-child(odd) { background: #eee; }
</style>
</head>
<body>
<ul id="messages"></ul>
<form action="">
<input id="m" autocomplete="off" /><button>Send</button>
</form>
</body>
</html>

如果你重启服务(按Control+C再运行node index.js),刷新页面,你会看到如下界面:

homepage

集成Socket.IO(Integrating Socket.IO)

Socket.IO由两部分组成:

  • 一个集成(或安装)了Node.js HTTP服务的服务器:socket.io

  • 一个加载在浏览器上的客户端库:socket.io-client

在开发时,socket.io为我们自动的服务客户端,就像我们看到的那样,所以现在我们只需要安装一个模块:

npm install –save socket.io

包管理工具会安装这个模块,并将依赖项添加到package.json。现在让我们在index.js中写入以下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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');
});
io.on('connection', function(socket){
console.log('a user connected');
});
http.listen(3000, function(){
console.log('listening on *:3000');
});

注意,我通过http(HTTP服务器)对象初始化了一个socket.io实例。然后,我监听sockets的connection事件,然后我使用console.log打印出它。

现在我们再index.html中添加如下代码,在</body>标签上方:

1
2
3
4
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io();
</script>

我们需要加载socket.io-client,它暴露了一个全局函数io,运行它,接着去连接服务器。

注意,当我调用io()时,不指定任何URL,因为它默认会尝试连接到这个页面的主机服务器。

如果你现在重启服务并刷新网页,你将看到终端打印出”a user connected”:

terminal

每个socket同样会触发一个特殊的disconnect事件:

1
2
3
4
5
6
io.on('connection', function(socket){
console.log('a user connected');
socket.on('disconnect', function(){
console.log('user disconnected');
});
});

接下来,你重启服务,刷新网页并关闭它,就可以看到事件的执行:

events

发射事件(Emitting events)

Socket.IO最主要的思想就是你可以发送和接收任何你想的事件、任何你想要的数据。任何对象都可以使用JSON进行编码,包括二进制数据同样支持。

让我们来实现,当用户发送一条信息时,服务器接收一个chat message事件。index.html的脚本部分修改成如下所示:

1
2
3
4
5
6
7
8
9
10
<script src="/socket.io/socket.io.js"></script>
<script src="http://code.jquery.com/jquery-1.11.1.js"></script>
<script>
var socket = io();
$('form').submit(function(){
socket.emit('chat message', $('#m').val());
$('#m').val('');
return false;
});
</script>

然后在index.js中,我们打印chat message事件:

1
2
3
4
5
io.on('connection', function(socket){
socket.on('chat message', function(msg){
console.log('message: ' + msg);
});
});

结果应该如下视频所示:

广播(Broadcasting)

下一个目标是,将发射的事件通过服务器广播给其他用户。

为了发送一个事件给每个用户,Socket.IO给了我们一个io.emit接口:

1
io.emit('some event', { for: 'everyone' });

如果你想发送一则消息给所有人,除了当前socket的拥有者,我们可以使用broadcast标记:

1
2
3
io.on('connection', function(socket){
socket.broadcast.emit('hi');
});

这这个实例中,为了简单起见,我们把消息发送给每一个人,包括消息的发出者:

1
2
3
4
5
io.on('connection', function(socket){
socket.on('chat message', function(msg){
io.emit('chat message', msg);
});
});

当客户端捕获到chat message事件,我们将消息插入到页面中。以下为客户端所有的JavaScript代码:

1
2
3
4
5
6
7
8
9
10
11
<script>
var socket = io();
$('form').submit(function(){
socket.emit('chat message', $('#m').val());
$('#m').val('');
return false;
});
socket.on('chat message', function(msg){
$('#messages').append($('<li>').text(msg));
});
</script>

完成我们的聊天室程序,只需要20行代码左右!它看起来像这样:

课后作业(Homework)

这里有一些点子来改善这个程序:

  • 当有人加入聊天室或退出聊天室时,广播一则消息给所有已连接的用户

  • 支持昵称功能

  • 不要向自己发送消息,而是在用户回车后立即添加消息到页面上

  • 增加”某某正在输入”的功能

  • 展示哪些人在线上

  • 增加私人消息传输

  • 展示你的改进结果!

获取示例(Getting this example)

你可以在GitHub上找到它。

点击获取示例

如果你电脑有装git,直接在项目目录下输入以下命令:

$ git clone https://github.com/guille/chat-example.git

本文作者:余震(Freak)
本文出处:Rockjins Blog
版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC-SA 3.0 CN许可协议。转载请注明出处!

坚持,您的支持将鼓励我继续爬下去!