基于Nodejs的长连接socket服务器
基于Nodejs的长连接socket服务器
在做flash游戏开发和服务器内网rpc通信的时候,经常使用的是4个字节的包头,这4个字节描述了包体的长度,包体一般是json文本数据,如果是rpc可能是二进制数据。
在erlang的网络库中对这种分包方式有底层库原生支持,在java的mina,netty网络库中也有支持,在node.js中需要我们自己来处理分包问题,还好githup上已经有了这样一个模块head_body_buffers模块,我们直接拿来用就好了,非常方便,具体请看https://github.com/freedaxin/head_body_buffers。下面直接上代码,基于这种分包协议的简单服务器端和客户端代码 <pre> <code> < /**
- User: dq
- Time: 13-6-28 上午10:04 */ var net = require(‘net’); var HeadBodyBuffers = require(’./lib/head_body_buffers’).HeadBodyBuffers;
function packetLength(data) { return data.readUInt32BE(0); }
var server = net.createServer(function(connection) { //‘connection’ listener console.log('new socket connected '); connection.setTimeout(2601000); connection.setNoDelay(true); var hdb = new HeadBodyBuffers(4, packetLength); hdb.on(‘packet’, function (packet) { var head = packet.slice(0, 4); var body = packet.slice(4); console.log(“body:”, body.toString(), body.length); connection.write(packet); });
connection.on('end', function() {
console.log('socket '+ connection +" closed ");
});
connection.on(‘data’,function(data){
hdb.addBuffer(data);
});
connection.on(‘timeout’,function(){
connection.end();
})
connection.on(‘error’,function(error){
console.error(error);
connection.end();
})
}); server.listen(11000, function() { console.log(‘server start’); });
server.on(‘error’,function(error){ console.error(error); })
// simple client test var client = net.connect(11000); var hbd = new HeadBodyBuffers(4, packetLength); hbd.on(‘packet’, function (packet) { var head = packet.slice(0, 4); var body = packet.slice(4); console.log(“body:”, body.toString(), body.length); client.write(packet); }) var keepAlive = ‘{type:“keepAlive”}’; var packet = new Buffer(4+ Buffer.byteLength(keepAlive)); packet.writeUInt32BE(Buffer.byteLength(keepAlive),0); packet.write(keepAlive,4); client.write(packet); client.on(‘data’, function(data) { hbd.addBuffer(data); }); </pre> </code>
基于Node.js的长连接Socket服务器
在开发某些应用时,如Flash游戏或服务器间通信,我们需要实现一种特定的协议,其中每个消息都包含一个4字节的头部,用于指示后续数据包的长度。在Node.js中,我们可以使用head_body_buffers
模块来简化这一过程。
示例代码
首先,你需要安装head_body_buffers
模块:
npm install head_body_buffers
接下来是服务器端代码:
const net = require('net');
const HeadBodyBuffers = require('./lib/head_body_buffers').HeadBodyBuffers;
// 计算数据包长度的函数
function packetLength(data) {
return data.readUInt32BE(0);
}
// 创建TCP服务器
const server = net.createServer((connection) => {
console.log('New socket connected');
// 设置超时时间
connection.setTimeout(2 * 60 * 1000);
connection.setNoDelay(true);
// 初始化HeadBodyBuffers实例
const hdb = new HeadBodyBuffers(4, packetLength);
// 监听packet事件
hdb.on('packet', (packet) => {
const head = packet.slice(0, 4);
const body = packet.slice(4);
console.log(`Received packet: ${body.toString()} with length ${body.length}`);
connection.write(packet); // 回复接收到的数据包
});
// 监听其他事件
connection.on('end', () => {
console.log(`Socket ${connection.remoteAddress}:${connection.remotePort} closed`);
});
connection.on('data', (data) => {
hdb.addBuffer(data);
});
connection.on('timeout', () => {
connection.end();
});
connection.on('error', (error) => {
console.error(error);
connection.end();
});
});
// 启动服务器
server.listen(11000, () => {
console.log('Server started on port 11000');
});
// 处理服务器错误
server.on('error', (error) => {
console.error(error);
});
客户端代码
接下来是客户端代码:
const net = require('net');
const HeadBodyBuffers = require('./lib/head_body_buffers').HeadBodyBuffers;
// 计算数据包长度的函数
function packetLength(data) {
return data.readUInt32BE(0);
}
// 创建客户端连接
const client = net.connect(11000, () => {
console.log('Connected to server');
});
// 初始化HeadBodyBuffers实例
const hdb = new HeadBodyBuffers(4, packetLength);
// 监听packet事件
hdb.on('packet', (packet) => {
const head = packet.slice(0, 4);
const body = packet.slice(4);
console.log(`Received packet from server: ${body.toString()} with length ${body.length}`);
client.write(packet); // 回复接收到的数据包
});
// 发送保持连接的消息
const keepAlive = '{type:"keepAlive"}';
const packet = Buffer.alloc(4 + Buffer.byteLength(keepAlive));
packet.writeUInt32BE(Buffer.byteLength(keepAlive), 0);
packet.write(keepAlive, 4);
client.write(packet);
// 监听数据接收事件
client.on('data', (data) => {
hdb.addBuffer(data);
});
解释
-
服务器端:
- 使用
net.createServer
创建一个TCP服务器。 HeadBodyBuffers
用于处理分包逻辑,通过packetLength
函数计算包体长度。hdb.on('packet', ...)
监听完整数据包,并打印其内容。connection.on('data', ...)
将接收到的数据传递给hdb
处理。- 设置超时和错误处理机制。
- 使用
-
客户端:
- 使用
net.connect
连接到服务器。 - 发送一条保持连接的消息。
- 接收并处理来自服务器的数据包。
- 使用
这种方式可以确保在长连接过程中正确地处理数据包的分隔和重组。
不错,希望以后能用上。
基于Node.js的长连接Socket服务器可以通过处理分包问题来实现。这里我将展示一个简单的示例代码,使用head_body_buffers
模块来处理消息的分包和重组。
示例代码
首先确保你已经安装了head_body_buffers
模块:
npm install head_body_buffers
然后可以使用以下代码创建一个简单的长连接Socket服务器:
服务器端代码
const net = require('net');
const HeadBodyBuffers = require('head_body_buffers').HeadBodyBuffers;
function packetLength(data) {
return data.readUInt32BE(0);
}
const server = net.createServer((connection) => {
console.log('New socket connected');
connection.setTimeout(2 * 60 * 1000);
connection.setNoDelay(true);
const hdb = new HeadBodyBuffers(4, packetLength);
hdb.on('packet', (packet) => {
const head = packet.slice(0, 4);
const body = packet.slice(4);
console.log("Body:", body.toString(), "Length:", body.length);
connection.write(packet);
});
connection.on('end', () => {
console.log('Socket ' + connection + ' closed');
});
connection.on('data', (data) => {
hdb.addBuffer(data);
});
connection.on('timeout', () => {
connection.end();
});
connection.on('error', (error) => {
console.error(error);
connection.end();
});
});
server.listen(11000, () => {
console.log('Server started');
});
server.on('error', (error) => {
console.error(error);
});
客户端代码
const net = require('net');
const HeadBodyBuffers = require('head_body_buffers').HeadBodyBuffers;
function packetLength(data) {
return data.readUInt32BE(0);
}
const client = net.connect(11000);
const hbd = new HeadBodyBuffers(4, packetLength);
hbd.on('packet', (packet) => {
const head = packet.slice(0, 4);
const body = packet.slice(4);
console.log("Body:", body.toString(), "Length:", body.length);
client.write(packet);
});
const keepAlive = '{type:"keepAlive"}';
const packet = Buffer.alloc(4 + Buffer.byteLength(keepAlive));
packet.writeUInt32BE(Buffer.byteLength(keepAlive), 0);
packet.write(keepAlive, 4);
client.write(packet);
client.on('data', (data) => {
hbd.addBuffer(data);
});
解释
-
服务器端:
- 创建一个TCP服务器监听11000端口。
- 使用
head_body_buffers
模块处理分包和重组。 - 监听
data
事件,将接收到的数据传递给hdb.addBuffer()
进行处理。 - 监听
packet
事件,处理完整的数据包并打印其内容。
-
客户端:
- 连接到服务器。
- 创建一个
HeadBodyBuffers
实例,并监听packet
事件以处理接收到的数据包。 - 发送一条包含
keepAlive
信息的消息到服务器。
通过这种方式,你可以轻松地处理基于固定长度头部的复杂协议,从而实现长连接Socket服务器。