阿男的小窝

View the Project on GitHub

Sever-Sent Events的协议分析

Sever-Sent Events是一种HTTP Server向Client推送的长连接协议,本文分析它的协议细节。

首先用写一个基于nodejs的的服务端代码:

var SSE = require('sse'), http = require('http');

var server = http.createServer(function(req, res) {
	res.writeHead(200, {'Content-Type'  : 'text/plain'});
	res.end('okay');
});

server.listen(8080, '127.0.0.1', function() {
	console.log("Starting server...");
	var sse = new SSE(server);
	sse.on('connection', function(client) {
		client.send('hi there!');
	});
});

可以把上面的代码命名为server.js,这个服务器代码使用了sse1这个库。 使用下面的命令来安装sse

$ npm install -g sse

其中-g选项是global的意思,就是把sse安装在node的全局目录位置。

安装完成以后,如果要使用sse这个库,就需要执行一下npmlink命令:

$ npm link sse

执行结果如下:

$ npm link sse
/Users/weli/node_modules/sse -> /usr/local/lib/node_modules/sse

连接好相关的库以后,就可以使用node命令执行server.js了:

$ node server.js
Starting server...

如上所示,可以看到server已经执行起来了。此时我们可以对server进行普通的http访问:

$ curl http://localhost:8080
okay

在这个位置不是SSE连接,而是普通的http请求。使用Wireshark进行协议分析如下:

注意编号为49的这个TCP packet,普通的HTTP访问结束后,客户端发起了FIN,结束连接的请求。也就是说,一次HTTP请求结束后,TCP连接就关闭了。

接下来我们访问服务端的SSE连接的位置:

可以看到,基于sse的访问请求后,客户端没有退出连接,而是hold在那里,等待服务端的更多数据推送。这个场景的协议分析如下:

如上所示,可以看到整个场景中,并没有FIN的请求发生,因此此时服务端和客户端之间的连接是保持的。

此外,注意第65号packet,这个packet其实是一个HTTP的packet,但是Wireshark没有把它表示成HTTP packet。我们可以点开这个packet的payload查看内容:

可以看到HTTP返回的内容,其中可以看到它的Content-Typetext/event-stream,这个是ServerSentEventmime-type

  1. https://www.npmjs.com/package/sse