2017-09-10 15 views
0

私はログファイルを作成し、新しい行をwebsocketにストリームします。ソケットIOが適切に接続を閉じていません

私は複数のログを持っているので、ユーザーにログファイルを選択させてから、そのログの詳細を取得させます。

問題は、別のログを見るために接続を閉じると、接続が変わってしまい、もう一度起動するとデータが2回ストリームされるということです。接続を閉じてもう一度やり直すと、データが3回ストリームされます。

マイpackage.json

{ 
    "socket.io": "^2.0.3", 
    "socket.io-client": "^2.0.3" 
} 

クライアント側

$("#detailsBtn").click(function (e) { 
    e.preventDefault(); 
    $.get('/get/details', { 
     // some-data 
    },() => { 
     if (socket) socket.close(); 
     socket = io('http://localhost:4000', {forceNew: true}); 
     socket.on('connect',() => { 
      console.log('connected'); 
     }); 
     socket.on('newLine', function (msg) { 
      // do-stuff 
     }); 
    }); 
}); 
$('#closeBtn').click(function() { 
    socket.disconnect(); 
    socket.close(); 
}); 

サーバー側

app.get('/details', (req, res) => { 
    const tail = spawn('ssh', ['[email protected]' + req.query.srv, req.query.script]); 
    io.on('connection', function (socket) { 
     console.log(`connect ${socket.id}`); 
     socket.on('disconnect',() => { 
      console.log(`DISconnected ${socket.id}`); 
     }); 
     tail.stdout.on('data', function (data) { 
      socket.emit('newLine', {message: data}); 
     }); 
    }); 
    return res.sendStatus(200); 
}); 

Now]ボタンのクリックをシミュレートするとき、私はSOCを期待ケットと接続を閉じて、新しいものを作る。

サーバーのコンソールログ(私は一度だけボタンをクリックするたびに)

Server listening on localhost:4000 

**click on detailsBtn** 
GET /get/details?srv=myserver.google.com&script=%2Fusr%2Fbin%2Ftail 304 16.003 ms - - 
connect YyYHFI9CARpBHaxoAAAB 
**click on closeBtn** 
DISconnected YyYHFI9CARpBHaxoAAAB 

**click on detailsBtn** 
GET /get/details?srv=myserver.google.com&script=%2Fusr%2Fbin%2Ftail 304 6.308 ms - - 
connect vzfBnUPHUqYXd5qaAAAC 
connect vzfBnUPHUqYXd5qaAAAC 
**click on closeBtn** 
DISconnected vzfBnUPHUqYXd5qaAAAC 
DISconnected vzfBnUPHUqYXd5qaAAAC 

**click on detailsBtn** 
GET /get/details?srv=myserver.google.com&script=%2Fusr%2Fbin%2Ftail 304 4.677 ms - - 
connect 3quEe5G1gFDJ2BvrAAAD 
connect 3quEe5G1gFDJ2BvrAAAD 
connect 3quEe5G1gFDJ2BvrAAAD 
**click on closeBtn** 
DISconnected 3quEe5G1gFDJ2BvrAAAD 
DISconnected 3quEe5G1gFDJ2BvrAAAD 
DISconnected 3quEe5G1gFDJ2BvrAAAD 

は私が間違って何をしているのですか?

+1

このような現象は、通常、重複イベントハンドラによって発生します。 – jfriend00

答えて

0

だからここのコメントは解決策を私に向けられます。

sockettailのイベントハンドラが重複していました。

ソケット

私は、ユーザーがボタンをクリックするたびに、接続の開始と呼ばれる、と私はspawntail子プロセスにURLがここ をアクセスしたたびに、エドは、私はそれを固定する方法であります

1.Moved @アレックス・rokabilisにより示唆されるようにapp.getハンドラのio.on('connection'...)

2.Created自分のemmiterイベント:

const events = require('events'); 
const eventEmitter = new events.EventEmitter(); 

3。io.on('connection'...)の内部では、代わりにtail.stdoutイベントに耳を傾け、私はapp.getハンドラ4.In

io.on('connection', function (socket) { 
    eventEmitter.on('newLine', (data) => { 
     socket.emit('newLine', {line: data}); 
    }); 
}); 

app.getハンドラのtail外を使用することができるようにするために、私のeventEmitterイベントに耳を傾け、私はtail.stdout.on('data'...に耳を傾け、送信しますioオブジェクトの内部処理されるeventEmitterイベント:

app.get('/details', (req, res) => { 
    let tail = spawn('ssh', ['[email protected]' + req.query.srv, req.query.script]); 
    tail.stdout.on('data', (data) => { 
     eventEmitter.emit('newLine', data.toString().replace(/\n/g, '<br />')); 
    }); 
}); 

5.Onクライアントは、私は、AJAX呼び出しの外で定義されたソケットIをio初期化を移動しました私はスクリプトでさらに使用することができます。

let socket = io('http://localhost:4000', {forceNew: true}); 
socket.on('connect',() => { 
    console.log('connected'); 
}); 
socket.on('newLine', function (msg) { 
    // do-stuff 
}); 

$("#detailsBtn").click(function (e) { 
    e.preventDefault(); 
    $.get('/get/details', { 
     // some-data 
    }); 
}); 

テール

これを見つけるのは少し大変でした、私はいつも問題がソケット-IOはなくtailであると思いました。

io.on('connection', function (socket) { 
    eventEmitter.on('newLine', (data) => { 
     socket.emit('newLine', {line: data}); 
    }); 
    socket.on('closeConnection',() =>{ 
     console.log('got connection close from client'); 
     eventEmitter.emit('closeConnection'); 
    }); 
}); 

そしてapp.getコントローラ内部:

app.get('/details', (req, res) => { 
    let tail = spawn('ssh', ['[email protected]' + req.query.srv, req.query.script]); 
    tail.stdout.on('data', (data) => { 
     eventEmitter.emit('newLine', data.toString().replace(/\n/g, '<br />')); 
    }); 
    eventEmitter.on('closeConnection',() => { 
     tail.stdin.pause(); 
     tail.kill(); 
    }); 
}); 
io.on('connection'...インサイド

は、私は順番にtail子プロセスを殺すことを、私のeventEmittercloseConnectionを発するcloseConnectionをという名前のイベントのためにソケットリスナーを追加しました

クライアントでは、接続を閉じるたびに、私はちょうど:

socket.emit('closeConnection'); 

これは厳しいものでした。

1

コンソールログに表示されているように、connectとdisconnectは同じsocketIDを示します。これは、イベントハンドラが何度もトリガされたことを示します。 '/details'ルートが要求を取得するたびに、コードから'connection'の新しいイベントハンドラを定義します。 だから、より良いaproachは...

io.on('connection', function (socket) { 
    console.log(`connect ${socket.id}`); 
    socket.on('disconnect',() => { 
     console.log(`DISconnected ${socket.id}`); 
    }); 
    tail.stdout.on('data', function (data) { 
     socket.emit('newLine', {message: data}); 
    }); 
}); 
app.get('/details', (req, res) => { 
    const tail = spawn('ssh', ['[email protected]' + req.query.srv, req.query.script]); 
    return res.sendStatus(200); 
}); 
+0

'tail is not defined 'というエラーがスローされます。また、 'tail.stdout'部分全体を' app.get'に移動してから、 'socket is not defined 'を試しました。 – Moshe

関連する問題