'use strict'; /** * 2个字节是16位(二进制),共能表示2^16=65536个数。但由于数是有符号的,最高位用作符号位,所以只有低15位表示绝对值。 * 整型在内存中以补码存储,能表示的最大正整数是2^15-1=32767。 */ const net = require('node:net'); const { Stick, MaxBodyLen } = require('@lvgithub/stick'); const stick = new Stick(1024).setReadIntBE('32'); stick.setMaxBodyLen(MaxBodyLen['2048M']); const LOCAL_PORT = 1936; /** * 头长度(Byte) */ const HEAD_LEN = 4; /** * 标识长度(Byte) */ const IDENTIFIER_LEN = 2; /** * 媒体服务器映射 */ const MEDIA_SERVER_MAP = new Map([ ['9999', { port: 1935, host: '192.168.66.73' }], ]); /** * 媒体服务器连接池 */ const MEDIA_SERVER_POOLS = new Map(); /** * 初始化多媒体服务器连接池 */ for (let [key, value] of MEDIA_SERVER_MAP) { const socket = net.createConnection({ host: value.host, port: value.port }); MEDIA_SERVER_POOLS.set(key, socket); } /** * 关闭所有目标服务器连接 */ const closeAllTargetSocket = function () { for (let [, value] of MEDIA_SERVER_POOLS) { value.end(); } }; const proxy = net.createServer(function (socket) { socket.on('data', function (data) { stick.putData(data); }); stick.onData(function (data) { const totalHeadLen = HEAD_LEN + IDENTIFIER_LEN; // 解析包头长度 const head = Buffer.alloc(HEAD_LEN); data.copy(head, 0, 0, HEAD_LEN); const dataLen = head.readInt32BE() - IDENTIFIER_LEN; // 解析标识 const identifier = Buffer.alloc(IDENTIFIER_LEN); data.copy(identifier, 0, HEAD_LEN, totalHeadLen); // 解析数据包内容 const body = Buffer.alloc(dataLen); data.copy(body, 0, totalHeadLen, head.readInt32BE() + HEAD_LEN); const mediaId = identifier.readInt16BE() + ''; console.log('data length: ' + dataLen); console.log('identifier content: ' + mediaId); // console.log('body content: ' + body.toString('hex')); if (MEDIA_SERVER_POOLS.has(mediaId)) { const mediaServer = MEDIA_SERVER_MAP.get(mediaId); console.log('matched media server: %s:%s', mediaServer.host, mediaServer.port); const targetSocket = MEDIA_SERVER_POOLS.get(mediaId); /** 测试代码START: 正式环境为一个代理网关对应多个媒体服务 */ if (targetSocket.listeners('data').length === 0) { targetSocket.on('data', function (chunk) { // TODO 向客户端回写需要实现推送一样的逻辑 socket.write(chunk); }); } if (targetSocket.listeners('close').length === 0) { targetSocket.on('close', function () { socket.end(); }); } /** 测试代码END */ targetSocket.write(body); } else { console.log('not match media server'); } }); socket.on('close', function () { closeAllTargetSocket(); console.log('client disconnected'); }); socket.on('error', function (error) { console.log(`error:客户端异常断开: ${error}`); }); }); proxy.on('error', function (err) { throw err; }); proxy.listen(LOCAL_PORT, function () { console.log('Zone2 proxy listening on ' + LOCAL_PORT); });