UDP 経由でデータを送信する必要がある場合、その制限に直面します。データは MTU に収まるように小さなチャンクで送信する必要があり、パケットは通知なしに失われたり、重複したり、順序が間違ったりする可能性があります。
uTP (マイクロ トランスポート プロトコル) は、UDP 経由でファイルを安全に送信するために torrent の人々によって発明されました。基本的には、TCP 機能を UDP に追加します。失われたパケットは自動的に再送信され、順序は保証され、重複は拒否されます。
このライブラリは UDP over UTP を実装しているため、接続すると、Node.js の TCP ソケットとよく似た動作をするソケットオブジェクトを受け取ります。データを受信するときに「データ」を出力し、バッファを送信するための .write() メソッドを備えています。 TCP ソケットと同様に、これは Node.js ストリームです。
ただし、このライブラリには次の機能が追加されるため、他の uTP 実装と互換性がない可能性があります (そのため、両方のピアでこの同じライブラリを使用する必要があります)。クラスの同じインスタンスをサーバーとサーバーの両方として使用できるクライアントを同じポート上で同時に実行します。したがって、ノードを作成してポートにバインドし、同時に受信接続のリッスンを開始し、そこから送信接続を確立することもできます。
npm install --save utp-punch
const Node = require('utp-punch');
let server = new Node(socket => {
console.log('server: socket connected');
socket.on('data', data => {
console.log(`server: received '${data.toString()}'`);
socket.write('world');
socket.end();
});
socket.on('end', () => {
console.log('server: socket disconnected');
server.close(); // this is how you terminate node
});
});
server.bind(20000, '127.0.0.1'); // bind to port 20000
server.listen( // run
() => console.log('server: ready')
);
let client = new Node();
client.bind(); // bind to any port
client.connect(20000, '127.0.0.1', socket => {
console.log('client: socket connected');
socket.on('data', data => console.log(`client: received '${data.toString()}'`));
socket.on('end', () => {
console.log('client: socket disconnected');
client.close(); // this is how you terminate node
});
socket.write('hello');
});
ここで使用されるもう 1 つの技術は、UDP ホールパンチです。
サーバーやクライアントが NAT の背後にある場合、通常、受信接続を受信するためにバインドするインターネット IP アドレスがありません。
UDP ホール パンチは、ファイアウォールをだましてユーザーに一時的なホールを開かせるため、NAT デバイスのポートが LAN 内のサーバー/クライアントのポートにバインドされます。
これが機能するためには、サーバーとクライアントの両方がサードパーティのサーバーを使用して、互いの NAT 化された IP アドレスを検索し、パンチング試行を調整する必要があります (これはサーバーとクライアントで同時に実行する必要があります)。
ただし、接続が確立されると、サードパーティ サーバーは必要なくなり、リレーとして使用されることもなくなり、すべてのデータがこの NAT サーバーとクライアントの間で直接送信されます。
const Node = require('utp-punch');
let server = new Node();
server.bind(20000);
let client = new Node();
client.bind(30000); // client needs dedicated port
// just as the server
// both server and client must contact a third party server
// which will report their peer NATed address and port to them
let serverAddress, serverPort;
let clientAddress, clientPort;
// up to ten punches:
server.punch(10, clientPort, clientAddress, success => {
// if success is true hole is punched from our side
// nothing to do here as the client will try
// to connect normally when he is also successful
});
client.punch(10, serverPort, serverAddress, success => {
if (success) {
client.connect(serverPort, serverAddress, socket => {
// if the server had also been successful in punching
// this will succeed
});
client.on('timeout', () => {
// if the server had failed in punching we won't be
// able to connect
});
}
});
example/ディレクトリにある完全な穴パンチの例を参照してください。
同じクラスをサーバーまたはクライアントとして使用できます。構文は次のとおりです。
オプションは次のとおりです。
{
bufferSize: 64, // number of packets
mtu: 1000, // bytes excluding uTP header
timeout: 5000, // ms
resend: 100, // ms
keepAlive: 1000, // ms
}
onConnection には単一の引数 (ソケット) が渡されます。これはサーバーの受信接続です
ノードが処理できる接続の最大数のゲッター
受信接続数のゲッター
発信接続数のゲッター
内部で使用される標準の Node.js UDP ソケットを返します。
ソケットのバインドされたアドレス (Node.js UDP .address() と同じ)
ホスト:ポートにバインドし、完了したら onBound を実行します
ホスト:ポートへのパンチ試行を開始し、成功したか試行が残っていない場合にコールバックを実行します。成功または失敗は、最初のブール値パラメータとしてコールバックに渡されます。
このノードをサーバーに変え、着信接続を受け入れる準備ができたらこのコールバックを実行します
ホスト:ポート上のサーバー ノードに接続し、ソケット オブジェクトを単一パラメータとしてコールバックを実行します。
すべての接続とノードを終了し、コールバックを実行します。
Node コンストラクターと .connect() コールバックに渡されるソケット オブジェクトは、データの受信時に「データ」を送信するストリームです。 .write()、.end() などの通常のメソッドがあります。
オリジナルの「utp」ライブラリは @mafintosh によって https://github.com/mafintosh/utp に作成されました。これは最新の JavaScript で書き直されたもので、バグ修正と、同じポート上でのサーバーとクライアントとしての同時使用や UDP ホールパンチのサポートなどの追加機能が含まれています。