基于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>


3 回复

基于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);
});

解释

  1. 服务器端

    • 创建一个TCP服务器监听11000端口。
    • 使用head_body_buffers模块处理分包和重组。
    • 监听data事件,将接收到的数据传递给hdb.addBuffer()进行处理。
    • 监听packet事件,处理完整的数据包并打印其内容。
  2. 客户端

    • 连接到服务器。
    • 创建一个HeadBodyBuffers实例,并监听packet事件以处理接收到的数据包。
    • 发送一条包含keepAlive信息的消息到服务器。

通过这种方式,你可以轻松地处理基于固定长度头部的复杂协议,从而实现长连接Socket服务器。

回到顶部