2017-09-04 95 views
0

我有很多设备将消息发送到写入节点的TCP服务器。 TCP服务器的主要任务是将一些消息路由到redis以便被另一个应用程序处理。node.js使用TCP服务器传输和保存文件

我写了一个简单的服务器,很好地完成了这项工作。代码的结构基本上是这样(不是实际的代码,细节隐藏):

const net = require("net"); 

net.createServer(socket => { 
    socket.on("data", buffer => { 
    const data = buffer.toString(); 
    if (shouldRouteMessage(data)) { 
     redis.publish(data); 
    } 
    }); 
}); 

大多数消息是这样的:{"text":"message body"},或{"lng":32.45,"lat":12.32}。但有时我需要处理一个消息,如跨越几个“数据”事件的消息,如{"audio":"...encoded audio..."}

在这种情况下,我需要将编码后的音频保存到文件中,并发送到redis {"audio":"path/to/audio-file.mp3"},其中路由是接收到音频数据的文件。

一个简单的选择是存储缓冲区,直到检测到消息结束并将其全部保存到文件中,但这意味着,除了别的以外,我必须在保存到磁盘之前将文件保留在内存中。

我希望有更好的选择,使用流和管道。有什么建议么? (一些代码示例,将是很好的)

感谢

回答

0

我终于解决了,所以我在这里发布的解决方案以作记录(以及一些运气,帮助他人)。

解决方案确实非常简单:只需打开一个写入流到一个文件并在数据包被接收时写入数据包。事情是这样的:

const net = require("net"); 
const fs = require("fs"); 

net.createServer(socket => { 
    socket.on("data", buffer => { 
    let file = null; 
    let filePath = null; 
    const data = buffer.toString(); 

    if (shouldRouteMessage(data)) { 
     // just publish the message 
     redis.publish(data); 
    } else if (isAudioStart(data)) { 
     // create a write stream to a file and write the first data packet 
     filePath = buildFilePath(data); 
     file = fs.createWriteStream(filePath); 
     file.write(data); 
    } else if (isLastFragment(data)) { 
     // if is the last fragment, write it, close the file and publish the result 
     file.write(data); 
     file.close(); 
     redis.publish(filePath); 
     file = filePath = null; 
    } else if (isDataFragment(data)) { 
     // just write (stream) it to file 
     file.write(data); 
    } 
    }); 
}); 

注:shouldRouteMessagebuildFilePathisDataFragment,并isLastFragment是依赖于数据的类型的自定义功能。

通过这种方式,输入数据是直接流到文件并且不需要将内容保存在内存之前。节点的溪流岩石!

一如既往的恶魔在细节中。例如,一些检查是必要的,例如,确保在您要写入文件时始终有一个文件。还记得转换为字符串时设置正确的编码(例如:buffer.toString('binary');为我做了诡计)。根据您的数据格式,shouldRouteMessageisAudioStart ...以及所有这些自定义功能可能更复杂或更简单。

希望它有帮助。

相关问题