[Nodejs实战]7-处理TCP服务

48 阅读2分钟

Nodejs如何处理Tcp的套接字,如何连接、沾包等 以koa框架为例

1.连接类 tcpServer.js 注意这里用一个全局变量socketMap存储socket连接有两个目的 1.单例模式,防止重复创建连接。2.连接分离,一个设备一个socket连接,防止窜数据等问题。

const net = require('net');
const { getDeviceNo } = require('./tcpUtils')
class TCPServer {
    constructor(options) {
        this.init(options);
    }
    init(options) {
        this.options = options;
        this.requestType = "";
        this.device = {};
    }
    createServer() {
        const TCP = net.createServer(this.options);
        global.socketMap = {};
        TCP.listen(this.options.port, () => {
            console.log(`server:${this.options.port}`);
        });
        TCP.on('connection', (socket) => {
            console.log('connection', socket.address())
            this.DealConnect(socket)
        });
        TCP.on('error', (err) => {
            throw err;
        });
    }
    DealConnect(socket) {
        socket.on('data', (data) => {
            //获取设备 一个设备建立一条socket链接
            global.socketMap["device_id"] = socket;
            //接收外部发送命令
            //handlerMsg(data)
        })
        // 客户端正常断开时执行
        socket.on('end', () => {
            console.log('client disconnected');
        });
        socket.on("error", function (err) {
            console.log('client error disconneted!');
        });
    }
}
module.exports = TCPServer;

2.启动类注入连接 app.js

const TCPServer = require('./utils/tcpServer');

const tcp_server = new TCPServer({port:config.tcp.port})
try {
  tcp_server.createServer();
} catch (err) {
  console.log(err);
}

3.工具类tcpUtils-发送tcp请求

/**
 * 构建发送数据格式
 * @param {*} param0 
 * @returns 
 */
const buildData = ({ len, oper, data }) => {
    const tcp_head = [0x0d, 0x24];//帧头
    const tcp_len = len;//长度
    const tcp_oper = oper;//操作码
    const tcp_data = data;//数据
    const tcp_vali = (tcp_len ^ tcp_oper ^ tcp_data).toString(16);//校验码
    const tcp_tail = [0x0d, 0x0a];//帧尾
    let sendDataStr = Buffer.from([...tcp_head, ...tcp_len, ...tcp_oper, ...tcp_data, tcp_vali, ...tcp_tail]);
    return sendDataStr;
}
/**
 * 发送数据
 * @param {data} param 
 */
const sendData = ({ data }, machine_no) => {
    let dataBuffer = buildData(data)
    console.log(`发送消息`, dataBuffer);
    console.log('machine_no', machine_no);
    const socket = global.socketMap[machine_no];
    try {
        socket.write(dataBuffer, '', () => {
            console.log(`发送消息返回`);
            return true
        })
    } catch (e) {
        console.log(e)
        console.log(`发送消息错误`);
        return false
    }
}
module.exports = {
    buildData,
    sendData
}

4.实际使用

const { sendData } = require('../utils/tcpUtils')
//设备请求登录反馈(jiajian)
const loginBack = (machine_no) => {
    let data = {
        len: [0x1d, 0x00],
        oper: [0x80],
        data: [0x17, 0x0a, 0x1a, 0x13, 0x0f, 0x0a, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
    };
    sendData({ data },machine_no);
}