问题
I'm following this tutorial to create Reactive TCP server in Nodejs
here's code that i've been working on
const Rx = require('rxjs')
const net = require('net')
const uuid = require('uuid');
module.exports = () => {
const sockets = new Map();
const ids = new Map();
const GetSocket = _id => sockets.get(_id);
const GetId = _socket => ids.get(_socket);
const SetSocket = _socket =>{
_socket.setEncoding('utf8');
const _id = uuid();
sockets.set(_id, _socket);
ids.set(_socket,_id);
return _id;
};
const server = net.createServer({ allowHalfOpen: true });
const socketStream = Rx.Observable.fromEvent(server, 'connection');
const RemoveSocket = socket = () => {
console.log("connection closed && removing socket from Map");
const id = ids.get(socket);
sockets.delete(id);
ids.delete(socket)
};
const socketObservable = socket => SetSocket(socket) &&
Rx.Observable
.of({
action: 'CONNECTION',
socket: GetId(socket)
})
.merge(
Rx.Observable
.fromEvent(socket,'data')
.map(d=>{
try {return JSON.parse(d);}
catch (e) {
console.log(e);
return d;
}
})
.map(msg=>{
return Object.assign({action:msg,socket:GetId(socket)})
})
)
.takeUntil(Rx.Observable.fromEvent(socket, 'close').map(d=>{
console.log("!!!! Should remove !!!");
RemoveSocket(socket);
}));
const Print = ()=>{
//ids.forEach(id=> console.log(GetSocket(id)));
console.log("total connected socket : " + ids.size);
};
const startServer = port => server.listen(port) &&
socketStream
.flatMap(socketObservable);
return {startServer, Print , stop: () => server.close()};
};
and here's my test result(just sending test msg and connect/reconnect to server )
{ action: 'CONNECTION',
socket: '8989b581-dc54-479b-a8c0-870cc8103c5b' }
total connected socket : 1
{ action: { test: 1 },
socket: '8989b581-dc54-479b-a8c0-870cc8103c5b' }
total connected socket : 1
{ action: { test: 2 },
socket: '8989b581-dc54-479b-a8c0-870cc8103c5b' }
total connected socket : 1
{ action: 'CONNECTION',
socket: 'b868104b-d1cf-41c9-950f-472f63bac27a' }
total connected socket : 2
{ action: { test: 1 },
socket: 'b868104b-d1cf-41c9-950f-472f63bac27a' }
total connected socket : 2
{ action: 'CONNECTION',
socket: 'b9a579fe-3715-4952-aaf7-d7f64a0bea99' }
total connected socket : 3
Everything working fine till detecting socket close event by TakeUntil() I tried using takewhile() by simply adding counter like this TakeWhile(cnt < 5) and socket stream completed as expected.
this is my first attempt to make something with Node.js and feel like i'm missing something.
can anyone help me to understand why takeUntil() is not working here? Thank you :)
回答1:
So my confusion was from understanding 'close' and 'end' events
'end' event gets triggered when the client disconnected or server calls socket.end(..) when server receives FIN packet
and 'close' event gets called after socket.destroy()
if anyone wants to see all socket events in action, I recommend watching this video
@Brannon, Thank you for pointing out the right event usage and thank you, everyone, for helping me out with this!!
also just in case, anyone wants working TCP server code.
dependency : rxjs 5.5.0
const Rx = require('rxjs');
const net = require('net');
const uuid = require('uuid');
module.exports = () => {
const sockets = new Map();
const ids = new Map();
const GetSocket = _id => sockets.get(_id);
const GetId = _socket => ids.get(_socket);
const SetSocket = _socket =>{
_socket.setEncoding('utf8');
const _id = uuid();
sockets.set(_id, _socket);
ids.set(_socket,_id);
return _id;
};
const server = net.createServer({ allowHalfOpen: true });
const socketStream = Rx.Observable.fromEvent(server, 'connection');
const RemoveSocket = socket => {
const id = ids.get(socket);
sockets.delete(id);
ids.delete(socket)
console.log("[server.js] socket closed..");
};
const socketObservable = socket => SetSocket(socket) &&
Rx.Observable
.of({
action: 'CONNECTION',
socket: GetId(socket)
})
.merge(
Rx.Observable
.fromEvent(socket,'data')
.map(d=>{
try {return JSON.parse(d);}
catch (e) {
console.log(e);
return d;
}
})
.map(msg=>{
return Object.assign({action:msg,socket:GetId(socket)})
})
)
.takeUntil(Rx.Observable.fromEvent(socket, 'end')
.map(()=>RemoveSocket(socket)));
const Print = ()=>{
//ids.forEach(id=> console.log(GetSocket(id)));
//ids.clear();
console.log("total connected socket : " + ids.size);
};
const startServer = port => server.listen(port) &&
socketStream
.flatMap(socketObservable);
console.log("[server.js] Starts Started" );
return {startServer, Print , stop: () => server.close()};
};
来源:https://stackoverflow.com/questions/51369830/need-help-on-using-takeuntil-and-observable-fromevent-methods