既に知っている方もいると思いますが、全てのサーバは2つの異なるポートで接続を待っています。まずひとつめはクライアントからサーバへの全ての直接接続を扱うTCPポート 4661があるとします。クライアントはサーバとの直接接続にTCP接続を使用します。ふたつめは他のサーバへの全ての接続用に、クライアントはポート 4665上のUDPを使用します。これはTCP/IPの特徴のひとつです。全てのTCP接続の申し入れは追加のデータを送信できるようになるまで、接続する相手によって承認されなければなりません(あまりに多すぎるアップロード→ダウンロードを持っている場合、他にアップロードスロットを使用している為、それ以上は受け付けられなくなります)。UDPはそれよりはるかに簡単に扱われます:我々が送信したデータを相手が受け取る事を保証しません。UDPは「届けばいいけど、別に余り気にしない」のです。したがって相手側のサーバがオーバーロードした場合、バッファからのパケットは中止され、dserverアプリケーションはあなたの要求を決して受け取ることはありません。UDPは一秒前に行ったアクションを再送することに意味がないような、オンラインゲーム等でよく使用されます!TCPとUDPとの間の違いを詳しく説明することは長くなりますのでやりません。仕様書を読むか、googleで検索して下さい。
サーバ上に入力TCP接続を持っていれば、これはログインしようとする(或いは既にログイン済みの)ユーザになります。ログインしようとするクライアントはまず始めにそのIPとポートを6バイト分サーバに送信します。もしサーバがユーザの最大数に達していれば、接続拒否応答を受信します。サーバは生きているが、dserverプロセスがあなたの要求を処理できない状態(OSは接続を受け付けたが、アプリケーションが利用できない場合)の時は、いつまでも「on queue(キュー)」で待機することができます。もし全てが問題ない場合はサーバはあなたの情報を受け付け、ログイン処理が継続されます。それからサーバはクライアントから指定されたIP/ポートで接続を開こうとします。サーバがあなたのクライアントとの接続を開くことに成功すれば、HighIDを取得し、さもなければサーバは内部の「ファイアーウォールされた」IDの1つを割り当てます。サーバはこのIDをあなたのクライアントに送信します。あなたのクライアントが以前持っていた物と違うIDを得ると「your ID has changed(IDが変更されました)」というメッセージが表示されます。
次にサーバはその名前と説明文、サーバリストと稼働ユーザ/ファイルを送信します。その後、あなたは自分の共有ファイルを登録し、それらはサーバのファイルインデックスに追加されます。
現在、接続が開かれていて、サーバ上で検索したり、あなたのダウンロードに他のソースを加えたりできます。この接続はホストかピアのどちらかが自発的に切断するまで開かれたままの状態になります。接続を閉じる信号を送信せずに一方が落ちると、相手はそのソケットで通信ができなくなるまでは接続が生きているものと考えます。例:あなたがアップロードしたい時、接続しているサーバが落ちている場合、あなたのクライアントはサーバを認識しません(もしサーバ管理者がサーバソフトウェアで終了作業を行った場合、接続を閉じる信号が送信されます)。これは正常なTCPの挙動であり、(クライアントがサーバとの接続を一定間隔でチェックしなければならないことは)回避することはできません。
実際には我々はUDPとTCP上で同じタスクを実行することができます(ただし、TCPでは「我々の」サーバと通信できるだけです)。(サーバ側からみて)緑はデータをダウンロードしたことを表し、赤はアップロードしたことを表します。
ソース要求
検索要求(これはクライアントがいくつかの特別な検索を定義することができる為、複雑になります)
統計要求
詳細要求
リスト要求
要求 | アップロード | ダウンロード | 付加情報 |
検索 | ファイル名、ハッシュ(16バイト)、様々な属性(各ファイルマッチ用) | 検索要求 | 全ての属性毎に2バイト+5バイト |
ログイン | ID(4バイト)、ウェルカムメッセージ+統計、詳細、サーバリスト | 共有ファイル(検索結果等) | ~10バイト |
ソース | ハッシュ(16バイト) | IP/ポート*ソース数(各6バイト) | 2バイト |
統計 | ユーザとファイル数(10バイト) | 無し | 2バイト |
詳細 | 名前と説明文 | 無し | 6バイト |
サーバリスト | IP/ポート*サーバ数(各6バイト) | 無し | 4バイト |
サーバが接続を試行するクライアントと接続できるなら、全てのサーバは全てのクライアントをチェックします。これは他のクライアントがこのソースに接続できることを保証し、サーバがこれを行えない場合は接続に失敗する為、このソースIDを別のクライアントに付与することは無駄になります。したがってサーバが直接クライアントに接続できない場合、サーバはこのクライアントにLowIDを割り当てることになります。その後、全てのクライアントがファイアーウォールされたユーザが共有するファイルのソースをこのサーバに問い合せることになります・・・そこでサーバはこのクライアントへ次のような応答を送信します「サーバx.x.x.x:4661上のユーザ 123はファイルを所持しています」。その後クライアントはこのサーバに再度問い合わせをします:「y.y.y.y:4662はユーザ 123との対話を希望」...サーバは「彼の」ユーザ 123に y.y.y.y:4662 との接続を開く必要があることを送信します...ファイアーウォールされたクライアントはy.y.y.y:4662との接続を開き、通信を開始します。それから他のクライアントはファイルzをダウンロードしたいといった問い合わせをファイアーウォールされたクライアントに対して行います。これはファイアーウォールされたユーザに接続することができる唯一の方法で、サーバがなければ誰も「ファイアーウォールされた」ユーザに接続することはできないでしょう。そしてこれが、ファイアーウォールされたユーザ同士がお互いに直接接続を作ることが絶対にできない理由となります。ファイアーウォールは全て他との接続を開く事をブロックします。
我々は検索が最もアップロード容量を必要とすることを見ることができます・・・また、検索の実行はサーバのCPU時間を最も多く消費します。通常サーバはRAMが十分にない為、既知の全てのMD4ハッシュのインデックスを使用し、メモリ全体を調べることなしにソースの為の要求を完了することができます。そしてその結果はスタックから直接やって来ます。ファイルリストは、全体のファイルのインデックスを検索する必要があるので、(ソート回数が少なかったとしても)「インデックスを付ける」ことは簡単ではありません。あらゆるファイルの結果は簡単に100~200バイトを超えるようになります。MP3は通常いくつかのID3タグ(タイトル、アルバム、アーティスト)を返します。その為その結果には1ファイルあたり多くのバイトを使用します...したがって200結果あるMP3の検索には50~100Kバイト程度必要になります。これは128kbpsの通常回線のアップロードでは全ての容量を使用しても5~10秒かかることを意味します...また、50キロバイトでは5000を超えるソースIP/ポートを他のクライアントに送信できます!
私の考えではサーバホッピングはサーバの大きな問題ではないように思えます。殆どのサーバが非同期回線上にあり、アップロードよりも多くのダウンロードができる為、(多くのファイルを共有するユーザの)追加ダウンロードを扱うことができるべきである。しかし、新規ファイルの解析とインデックスにそれを追加する作業はサーバのCPU時間を消費します。しかしこれはファイアーウォールされたユーザの問題です。なぜなら、彼らはサーバに接続した時に「利用可能」だからです。