Node.js net.createConnection() 実践:複数クライアント接続とタイムアウト設定

2025-04-26

基本的な説明

  • UNIXドメインソケット接続
    • UNIXベースのシステムでは、ファイルパスを指定することで、ローカルプロセス間の通信にUNIXドメインソケットを使用できます。
    • これは、同じマシン上で動作するプロセス間の高速な通信を可能にします。
  • TCP接続
    • net.createConnection()は、IPアドレスとポート番号を指定することで、リモートサーバーとのTCP接続を確立します。
    • これは、クライアントがサーバーと通信する必要がある場合に非常に便利です。たとえば、HTTPクライアントやデータベースクライアントなどがこれを使用します。

関数の構文

net.createConnection(options[, connectListener]) net.createConnection(port[, host][, connectListener]) net.createConnection(path[, connectListener])

  • connectListener: 接続が確立されたときに呼び出されるコールバック関数。
  • path: UNIXドメインソケットのパス。
  • host: 接続先のホスト名またはIPアドレス。
  • port: 接続先のポート番号。
  • options: 接続オプションを含むオブジェクト。


TCP接続の例

const net = require('net');

const client = net.createConnection({ port: 8080, host: '127.0.0.1' }, () => {
  console.log('サーバーに接続しました!');
  client.write('Hello, server!\\r\\n');
});

client.on('data', (data) => {
  console.log(`サーバーからのデータ: ${data.toString()}`);
  client.end();
});

client.on('end', () => {
  console.log('サーバーとの接続が終了しました。');
});

client.on('error', (err) => {
    console.error(`エラーが発生しました:${err}`);
});

この例では、net.createConnection()を使用してローカルホストの8080ポートに接続し、データを送受信しています。

UNIXドメインソケット接続の例

const net = require('net');

const client = net.createConnection({ path: '/tmp/my_socket' }, () => {
  console.log('UNIXドメインソケットに接続しました!');
  client.write('Hello, UNIX socket!\\r\\n');
});

client.on('data', (data) => {
  console.log(`UNIXソケットからのデータ: ${data.toString()}`);
  client.end();
});

client.on('end', () => {
  console.log('UNIXソケットとの接続が終了しました。');
});

client.on('error', (err) => {
    console.error(`エラーが発生しました:${err}`);
});

この例では、/tmp/my_socketにあるUNIXドメインソケットに接続しています。

net.createConnection()は、Node.jsでTCPまたはUNIXドメインソケット接続を確立するための重要な関数です。これを使用することで、クライアントはサーバーと通信し、データを送受信できます。



接続拒否 (Connection Refused)

  • UNIXドメインソケットの場合
    ソケットファイルが存在するか、正しいパスが指定されているか確認してください。
  • トラブルシューティング
    • サーバーが正しく起動しているか確認してください。
    • ポート番号とホスト名/IPアドレスが正しいか確認してください。
    • ファイアウォール設定を確認し、接続を許可してください。
    • サーバー側のログを確認し、エラーメッセージがないか確認してください。
  • 原因
    指定されたホストまたはポートでサーバーが実行されていない、またはサーバーが接続を受け付けていない可能性があります。ファイアウォールが接続をブロックしている可能性もあります。
  • エラーメッセージの例
    Error: connect ECONNREFUSED 127.0.0.1:8080

接続タイムアウト (Connection Timeout)

  • トラブルシューティング
    • サーバーが応答しているかpingコマンドなどで確認してください。
    • ネットワーク接続を確認してください。
    • 接続タイムアウト時間を調整してみてください。net.createConnection()optionsオブジェクトでtimeoutプロパティを設定できます。
    • サーバー側で処理に時間がかかっている可能性もあるため、サーバー側のパフォーマンスも確認してください。
  • 原因
    サーバーが応答しない、またはネットワーク接続が遅延している可能性があります。
  • エラーメッセージの例
    Error: connect ETIMEDOUT 127.0.0.1:8080

アドレスが使用中 (Address Already in Use)

  • トラブルシューティング
    • 別のプロセスがポートを使用していないか確認してください。netstatコマンドやlsofコマンドを使用して、ポートを使用しているプロセスを特定できます。
    • 別のポートを使用するようにサーバーを設定してください。
    • サーバーを再起動する前に、以前のプロセスが完全に終了していることを確認してください。
  • 原因
    指定されたポートが別のプロセスによって使用されています。
  • エラーメッセージの例
    Error: listen EADDRINUSE :::8080 (サーバー側で発生)

ソケットエラー (Socket Errors)

  • EPIPE
    パイプが壊れている。クライアントかサーバーの接続が切れた状態で、書き込みをすると発生します。
  • トラブルシューティング
    • サーバー側のログを確認し、エラーメッセージがないか確認してください。
    • ネットワーク接続が安定しているか確認してください。
    • クライアントとサーバーの両方で、エラー処理を適切に行っているか確認してください。
    • クライアントとサーバー間の通信プロトコルが一致しているか確認してください。
  • 原因
    接続が予期せず閉じられた、またはソケットでエラーが発生しました。
  • エラーメッセージの例
    Error: read ECONNRESET, Error: write EPIPE

ホスト名解決エラー (Hostname Resolution Error)

  • トラブルシューティング
    • ホスト名が正しいか確認してください。
    • DNSサーバーが正しく設定されているか確認してください。
    • ネットワーク接続を確認してください。
  • 原因
    指定されたホスト名をIPアドレスに解決できませんでした。
  • エラーメッセージの例
    Error: getaddrinfo ENOTFOUND example.com
  • ドキュメントを読む
    Node.jsのnetモジュールのドキュメントを読んで、関数の使い方やエラー処理について理解を深めてください。
  • 単純なテストを行う
    問題を特定するために、単純なクライアントとサーバーを作成してテストしてみてください。
  • ネットワークツールを使用する
    ping, traceroute, netstat, tcpdumpなどのネットワークツールを使用して、ネットワーク接続やサーバーの状態を確認してください。
  • ログを確認する
    クライアントとサーバーの両方のログを確認し、エラーメッセージや警告がないか確認してください。
  • エラーメッセージをよく読む
    エラーメッセージには、問題の原因に関する重要な情報が含まれています。


基本的なTCPクライアント

const net = require('net');

const client = net.createConnection({ port: 8080, host: '127.0.0.1' }, () => {
  console.log('サーバーに接続しました!');
  client.write('Hello, server!\\r\\n'); // サーバーにデータを送信
});

client.on('data', (data) => {
  console.log(`サーバーからのデータ: ${data.toString()}`); // サーバーからのデータを受信
  client.end(); // 接続を終了
});

client.on('end', () => {
  console.log('サーバーとの接続が終了しました。');
});

client.on('error', (err) => {
  console.error(`エラーが発生しました:${err}`);
});
  • client.on('error', ...)でエラー処理を行います。
  • client.end()で接続を終了します。
  • client.write()でサーバーにデータを送信し、client.on('data', ...)でサーバーからのデータを受信します。
  • net.createConnection()でサーバーへの接続を確立し、接続が成功するとconnectイベントが発生し、コールバック関数が実行されます。
  • このコードは、ローカルホストの8080ポートに接続する基本的なTCPクライアントです。

タイムアウト設定

const net = require('net');

const client = net.createConnection({ port: 8080, host: '127.0.0.1', timeout: 5000 }, () => {
  console.log('サーバーに接続しました!');
  client.write('Hello, server!\\r\\n');
});

client.on('data', (data) => {
  console.log(`サーバーからのデータ: ${data.toString()}`);
  client.end();
});

client.on('timeout', () => {
  console.log('接続がタイムアウトしました。');
  client.end();
});

client.on('error', (err) => {
  console.error(`エラーが発生しました:${err}`);
});
  • この例では、5000ミリ秒(5秒)以内に接続が確立されない場合、timeoutイベントが発生します。
  • optionsオブジェクトにtimeoutプロパティを追加することで、接続タイムアウトを設定できます。

UNIXドメインソケットクライアント

const net = require('net');
const socketPath = '/tmp/my_socket'; // UNIXドメインソケットのパス

const client = net.createConnection({ path: socketPath }, () => {
  console.log('UNIXドメインソケットに接続しました!');
  client.write('Hello, UNIX socket!\\r\\n');
});

client.on('data', (data) => {
  console.log(`UNIXソケットからのデータ: ${data.toString()}`);
  client.end();
});

client.on('end', () => {
  console.log('UNIXソケットとの接続が終了しました。');
});

client.on('error', (err) => {
  console.error(`エラーが発生しました:${err}`);
});
  • この例では、/tmp/my_socketにあるUNIXドメインソケットに接続します。
  • optionsオブジェクトにpathプロパティを指定することで、UNIXドメインソケットに接続できます。
const net = require('net');

for (let i = 0; i < 3; i++) {
  const client = net.createConnection({ port: 8080, host: '127.0.0.1' }, () => {
    console.log(`クライアント ${i + 1} が接続しました!`);
    client.write(`クライアント ${i + 1} からのメッセージ\\r\\n`);
  });

  client.on('data', (data) => {
    console.log(`クライアント ${i + 1} が受信: ${data.toString()}`);
    client.end();
  });

  client.on('end', () => {
    console.log(`クライアント ${i + 1} が切断しました。`);
  });

  client.on('error', (err) => {
    console.error(`クライアント ${i + 1} でエラーが発生しました:${err}`);
  });
}
  • 各クライアントは、異なるメッセージをサーバーに送信し、サーバーからの応答を受信します。
  • このコードは、ループを使用して複数のクライアントを同時にサーバーに接続する例です。


net.connect()

  • 構文と使い方はnet.createConnection()と全く同じです。
  • コードの可読性を向上させるために、より直感的なnet.connect()を使用することもできます。
  • net.connect()net.createConnection()のエイリアスであり、機能は全く同じです。
const net = require('net');

const client = net.connect({ port: 8080, host: '127.0.0.1' }, () => {
  console.log('サーバーに接続しました!');
  // ...
});

socket.connect()

  • net.createConnection()またはnet.connect()は内部的にnet.Socketオブジェクトを作成してconnect()メソッドを呼び出しています。
  • net.Socketオブジェクトは、ソケット通信をより細かく制御する必要がある場合に便利です。
  • net.Socketオブジェクトを作成し、そのconnect()メソッドを使用する方法です。
const net = require('net');

const socket = new net.Socket();

socket.connect({ port: 8080, host: '127.0.0.1' }, () => {
  console.log('サーバーに接続しました!');
  socket.write('Hello, server!\\r\\n');
});

socket.on('data', (data) => {
  console.log(`サーバーからのデータ: ${data.toString()}`);
  socket.end();
});

// ...
  • net.Socketオブジェクトを使用すると、socket.setTimeout()socket.setNoDelay()などのメソッドを使用して、ソケットの動作をより細かく制御できます。

HTTP/HTTPSモジュール

  • http.request()https.request()を使用して、HTTP/HTTPSリクエストを送信できます。
  • これらのモジュールは、HTTP/HTTPSプロトコルを抽象化し、より高レベルなAPIを提供します。
  • HTTPまたはHTTPS通信を行う場合、netモジュールを直接使用する代わりに、httpまたはhttpsモジュールを使用するのが一般的です。
const http = require('http');

const options = {
  hostname: '127.0.0.1',
  port: 8080,
  path: '/api/data',
  method: 'GET'
};

const req = http.request(options, (res) => {
  console.log(`ステータスコード: ${res.statusCode}`);

  res.on('data', (chunk) => {
    console.log(`データ: ${chunk}`);
  });
});

req.on('error', (err) => {
  console.error(`エラー: ${err}`);
});

req.end();
  • HTTP/HTTPS通信では、netモジュールを直接使用するよりも、httpまたはhttpsモジュールを使用する方がコードが簡潔になり、エラー処理も容易になります。
  • WebSocketは、双方向のリアルタイム通信を可能にするプロトコルであり、チャットアプリケーションやリアルタイムゲームなどで使用されます。
  • WebSocket通信を行う場合、wsなどのWebSocketクライアントライブラリを使用するのが一般的です。
const WebSocket = require('ws');

const ws = new WebSocket('ws://127.0.0.1:8080');

ws.on('open', () => {
  console.log('WebSocket接続が確立されました!');
  ws.send('Hello, WebSocket server!');
});

ws.on('message', (data) => {
  console.log(`サーバーからのメッセージ: ${data}`);
});

ws.on('close', () => {
  console.log('WebSocket接続が閉じられました。');
});
  • WebSocket通信では、netモジュールを直接使用するよりも、WebSocketクライアントライブラリを使用する方がコードが簡潔になり、WebSocketプロトコルの詳細を意識する必要がなくなります。
  • WebSocket通信では、WebSocketクライアントライブラリを使用するのが一般的です。
  • HTTP/HTTPS通信では、httpまたはhttpsモジュールを使用するのが一般的です。
  • net.Socketオブジェクトを使用すると、ソケット通信をより細かく制御できます。
  • net.connect()net.createConnection()のエイリアスです。