网络服务通常要做两件事情:建立连接和传输信息。
涉及到的代码见git地址node-js-demo
socket通信
服务器端代码如下,服务端代码存在server.js里面
const fs = require('fs');
const net = require('net');
const filename = process.argv[2];
if (!filename) {
console.log('文件不存在!');
return;
}
const server = net.createServer((connection) => {
console.log('已建立连接');
connection.write('现在开始监听文件内容变化'+ '\n'));
const watcher = fs.watch(filename, () => {
connection.write('file changed' + '\n');
})
connection.on('close', () => {
console.log('连接关闭');
watcher.close();
})
});
server.listen(60300, () => {
console.log('server is listening 60300');
})
服务端运行命令:
node server.js target.txt
客户端运行命令:
telnet 127.0.0.1 60300
//客户端命令也可以是 telnet localhost 60300
客户端与服务端建立连接后,服务器端监听目标文件内容的变化,如果文件内容有变化,则通过connection.write 把消息传输到客户端。
消息拆分处理
Nodejs在消息通信时,有时消息可能会被切分成几块数据,该如何处理呢?
例如,当文件内容改变时,我们要传给客户端一个字符串,一个带有type、timestamp属性的对象和换行符。
connection.write(JSON.stringify({type: 'changed', timestamp: Date.now()}) + '\n');
客户端监听data事件,就可以拿到服务器端传输来的数据:
const client = require('net').connect({port: 60300});
client.on('data', data => {
const message = JSON.parse(data);
console.log('message', message)
})
可是如果服务器端这样拆分数据,把一条完整的消息拆分成两条:
const firstChunk = '{"type": "changed", "timesta';
const secondChunk = 'mp": 1450694370094}\n';
客户端这时候就会报错了。
解决思路就是先把接收到的原始消息存到buffer变量中,然后从前往后查找消息结束符,我们这里的消息结束符是‘\n’,找到‘\n’时把这条消息取出来,解析后输出到客户端。
const client = require('net').connect({
port: 60300
});
var buffer = '';
client.on('data', data => {
buffer+= data;
let boundary = buffer.indexOf('\n');
console.log('buffer', buffer.toString());
while(boundary !== -1) {
const input = buffer.substring(0, boundary);
buffer = buffer.substring(boundary + 1);
console.log('message', JSON.parse(input));
boundary = buffer.indexOf('\n');
}
})