I have question about forking TCP client in Node JS. Here's the scenario.
Here are my approachment so far.
// tcp_client.js
const cluster = require('cluster')
if (cluster.isMaster) {
for (let i = 0; i < 2; i += 1) {
setTimeout(() => {
cluster.fork()
}, 8000) // I expect this will delay between one and another fork
}
} else {
console.log(`Connected on ${process.pid}`)
require('./sender').send()
}
cluster.on('exit', (worker) => {
console.log('server',`Worker %d died :( ${worker.id}`);
cluster.fork();
})
// sender.js
const net = require('net')
const send = () => {
const client = new net.Socket()
client.connect(8090, 'localhost', () => {
const firstMessage = 'first_message'
const secondMessage = 'second_message'
const write = function () {
client.write(firstMessage)
/*
The reason why I'm using setTimeout() is because if I write it as
`client.write(firstMessage)
client.write(secondMessage)`
The second message won't be sent. Is there any better methods?
*/
setTimeout(() => {
client.write(secondMessage)
}, 1);
}
setTimeout(write, 5000) // I expect this will loop infinitely
})
}
module.exports = { send }
When I run the code the fork isn't delayed and the message won't loop. Is there any solution? Thank you.
If you want your two forks to be 8 seconds apart, you would need a varying time on the setTimeout()
. setTimeout()
is not blocking so all your code was doing was scheduling two setTimeout()
s - each for 8 seconds from now. This will schedule one for 8 seconds and one for 16 seconds:
// tcp_client.js
const cluster = require('cluster')
if (cluster.isMaster) {
for (let i = 0; i < 2; i += 1) {
setTimeout(() => {
cluster.fork()
}, (i + 1) * 8000);
}
} else {
console.log(`Connected on ${process.pid}`)
require('./sender').send()
}
cluster.on('exit', (worker) => {
console.log('server',`Worker %d died :( ${worker.id}`);
cluster.fork();
})
And, your write code isn't looping because the setTimeout(write, 5000)
is inside the connect
event handler, not inside the write()
function. So, it gets called once when the connect
event fires and never gets called again. If you want write()
to repeat, then put this inside the write()
function itself (or use setInterval()
).
// sender.js
const net = require('net')
const send = () => {
const client = new net.Socket()
client.connect(8090, 'localhost', () => {
const firstMessage = 'first_message'
const secondMessage = 'second_message'
const write = function () {
client.write(firstMessage)
setTimeout(() => {
client.write(secondMessage)
}, 1);
setTimeout(write, 5000) // I expect this will loop infinitely
}
write();
})
}
module.exports = { send }
Also, it's perfectly OK to do two client.write()
calls like this in a row - both will be sent. But, TCP will probably combine them into the same packet. TCP is a stream protocol, not a message-based protocol. So, to delineate the difference between messages, you have to parse the stream upon reading. You should not rely on data arriving in exactly the same chunks in which it was sent. It can be broken up into smaller chunks or multiple separately written chunks can be combined into the same arriving packet. For example, in this case, you could just put a \n at the end of each message and use that as a message delimiter when reading the TCP stream so you could parse each incoming message separately, even if they were combined by TCP into the same packet.
Or you can use a message based protocol on top of TCP like webSocket that does the packing and unpacking into distinct messages for you and will deliver only a finished and separate message to you.