web-dev-qa-db-ja.com

node.js-処理TCPソケットエラーECONNREFUSED

Socket.ioでnode.jsを使用して、TCPソケットによって提供される文字データにWebページにアクセスできるようにします。node.jsはまったく新しいです。

User---->Webページ< ソケット。 io)->node.js<-(TCP)->TCPサーバー

コードは容赦なく簡潔です:

io.on('connection', function (webSocket) {
    tcpConnection = net.connect(5558, 'localhost', function() {});

    tcpConnection.on('error', function(error) {
        webSocket.emit('error', error);
        tcpConnection.close();
    });

    tcpConnection.on('data', function(tcpData) {
        webSocket.emit('data', { data: String.fromCharCode.apply(null, new Uint8Array(tcpData))});
    });
});

通常の場合はすべて正常に機能しますが、TCPサーバーが常に存在することを保証することはできません。そうでない場合、TCPスタックはnode.jsにECONNREFUSEDを返します-これは完全に予期されたものであり、適切に処理する必要があります。

events.js:72
    throw er; // Unhandled 'error' event
          ^
Error: connect ECONNREFUSED
    at errnoException (net.js:904:11)
    at Object.afterConnect [as oncomplete] (net.js:895:19)

...そして、プロセス全体が終了します。

私はこれに対する解決策をたくさん探しました。ほとんどのヒットは、最初にECONNREFUSEDが受信される理由を尋ねるプログラマーからのものであるようです。アドバイスは、TCPサーバーが利用可能であることを確認することです。

この投稿----(Node.js connectListenerはまだソケットエラーで呼び出されています -上記のコードで行ったように、「エラー」イベントのハンドラーを追加することをお勧めします。これはまさに私がそれを動作させたい方法です...それは(私にとって)そうではないことを除いて、私のプログラムはECONNREFUSEDをトラップしません。

私はRTFMを試みましたが、node.jsのドキュメント http://nodejs.org/api/net.html#net_event_error_1 は実際には「エラー」イベントがあることを示唆していますが、使い方の手がかり。

他の同様のSO投稿( Node.js Error:connect ECONNREFUSED など)への回答は、グローバルなキャッチされていない例外ハンドラーにアドバイスしますが、これは私にとっては貧弱なソリューションのようです。これは、悪いコードが原因で例外をスローするプログラムではなく、正常に動作しています-設計どおりに外部障害を処理することになっています。

そう

  • 私はこれに正しい方法でアプローチしていますか? (これは初心者のエラーであることを認めて喜んでいます)
  • 私がやりたいことをすることは可能ですか?

ああ、そして:

$ node -v
v0.10.31
19
Chris Mead

私は次のコードを実行しました:

var net = require('net');

var client = net.connect(5558, 'localhost', function() {
  console.log("bla");
});
client.on('error', function(ex) {
  console.log("handled error");
  console.log(ex);
});

5558を開いていないので、出力は次のとおりです。

$ node test.js
handled error
{ [Error: connect ECONNREFUSED]
  code: 'ECONNREFUSED',
  errno: 'ECONNREFUSED',
  syscall: 'connect' }

これは、エラーが適切に処理されることを証明しています...エラーが他の場所で発生していることを示唆しています。

別の回答で説明したように、問題は実際には次の行です。

webSocket.emit('error', error);

「エラー」イベントは特別であり、どこかで処理する必要があります(そうでない場合、プロセスは終了します)。

イベントの名前を「問題」または「警告」に変更すると、エラーオブジェクト全体がsocket.ioソケットを介してWebページに送信されます。

webSocket.emit('warning', error);
19
alandarev

これを修正するために私が見つけた唯一の方法は、ドメインにネットのものをラップすることです:

const domain = require('domain');
const net = require('net');

const d = domain.create();

d.on('error', (domainErr) => {
    console.log(domainErr.message);
});

d.run(() => {
    const client = net.createConnection(options, () => {

        client.on('error', (err) => {
            throw err;
        });
        client.write(...);
        client.on('data', (data) => {
            ...
        });
    });
});

ドメインエラーは、無効なホストなど、ネットクライアントが作成される前に発生するエラー状態をキャプチャします。

参照: https://nodejs.org/api/domain.html

0
Jan Bauer