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