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