socket.io Get started/chat

本文属于原创文章,转载请注明–来自桃源小盼的博客

socket.io非常适合做聊天室,但英文官网读起来还是有一定的障碍,特此翻译。如有误点,欢迎指出。

1
原地址:http://socket.io/get-started/chat/

正文如下:

开始:聊天

本篇文章,我们将一起来创建一个简单的聊天应用。它几乎不要求你提前掌握Node.JS 或 Socket.IO的知识,适合任何人来尝试。

介绍

用LAMP这种传统的方式来搭建一个聊天应用是很难的,它包括轮询服务器的变化,保持跟踪时间戳,比socket.io慢得多。

Sockets一直是最具实时性的聊天系统解决方案,在客户端和服务端提供了一种双向通信通道。

这意味着服务器能发送消息给客户端。当你发出一条消息时,服务端将获取它,并将它发送给其他所有在线客户端。

使用web框架 express

首要目标是建立一个简单的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

1
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');
});

说明如下:

  • Express初始化app为一个处理请求HTTP服务的程序。(参见第二行)
  • 定义一个路由/访问网站根目录
  • 监听HTTP服务器端口3000

如果你运行node index.js,将看到如下界面:

socket-io-1

紧接着我们用浏览器访问http://localhost:3000

socket-io-2

编辑HTML(Serving HTML)

现在我们在index.js中使用res.send传递一个HTML字符串。如果我们把整个应用的的HTML放在index.js中,整个代码结构将杂乱无章。所以我们要创建一个index.html文件。

我们要使用sendFile方法来重构路由管理。

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>

如果你重启进程(ctrl+C并再次运行node index)并且刷新浏览器,效果如下:

socket-io-3

整合Socket.IO

Socket.IO由两部分构成:

  • 服务端使用Node.JS的HTTP服务器: socket.io
  • 客户端则在浏览器端加载:socket.io-client

开发期间,socket.io自动在客服端运行加载,现在我们必须要安装一个模块:

1
npm install --save socket.io

上面的命令将安装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实例。接着监听socket连接事件,并将它输出到控制台。

然后在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”。

尝试打开多个页面,你将看到如:

socket-io-4

每个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');
});
});

如果你刷新一个页面几次,你将在控制台看到如下信息:

socket-io-5

发送事件(Emitting)

Socket.IO背后的主要思想是:你可以发送和接收任何你想要的事件和数据。任何被编码为JSON的对象,二进制数据也支持。

当用户输入一条消息时,服务端把它当作chat message事件获得。在index.html中的script片段如下:

1
2
3
4
5
6
7
8
9
10
<script src="https://cdn.socket.io/socket.io-1.2.0.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);
});
});

结果如下:(原文是一小片段视频,此处无法加进来,截图展示)

socket-io-6

通知(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
6
7
8
9

现在为了简单起见,我们发送消息给每个人,包括发送者自己。

``` javascript
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
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));
});

现在我们的聊天应用完成了,大约20行代码,最后就是这样子了:(原文是一小片段视频,此处无法加进来,截图展示)

socket-io-7

更多的实践

这有一些建议来改进这个应用:

  • 当有人进入或离开时,通知给所有人。
  • 增加昵称
  • 不发送相同的消息给发送者自己,反而当输入回车时快速发送消息。
  • 增加“用户正在输入”功能
  • 展示谁在线
  • 增加私信
  • 分享你的改进

获得这个例子

在GitHub上你能找到它

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

译者说:

这篇文章还是有几处我没有翻译好的地方,作为一个coder必须要把英语学好。好事多磨,编程也不要过分地追求速度。