Bash:Macでのネットワークゲームの敵の自動検出

ときどきbashにささいなことを書くのが好きです。 私がすでに「Habr」で話したネットワークチェスのように。



最近、私は精神的に彼らに戻り、ゲーム自体がオンラインでプレイするためのパートナーを見つけることができたらどんなに素晴らしいだろうと考えました。 つまり おもちゃが発売されると、どうにかしてネットワークを検索して、戦いの準備ができている人を探します。



一般に、すべてのアドレスをスキャンすることは長時間不可能です。 2つのtwoい「正面」ソリューションがあります-現在のサブネットをスキャンするか、 ARPテーブルを見て、そこにいる人に接続します。 しかし、第一に、このソートは依然として低速であり、第二に、潜在的なライバルをすべて見つけることができません(ライバルは他のサブネット上にあり、 ARPテーブル内のすべてのネットワーク参加者ではありません)。



一般に、OSで同様の問題がかなり前に解決されました。たとえば、自宅でネットワークプリンターをセットアップしたとき、オペレーティングシステムが自分で見つけたので、 IPなどを指定しませんでした。 このための「Mac」には、 Bonjourテクノロジー( Zerokonfの実装)があります。



このテクノロジーをBashで使用することは可能ですか?



私はネットワークチェスを書き直さず、すべてを開始したという考えで、代わりに、次のアルゴリズムに従って動作するファイル転送ユーティリティを作成しようとしました:2台のマシンで実行され、コンピュータがお互いを見るとどのファイルを転送する必要があるかを示しますネットワーク、次にファイルが転送されます。 これらはすべてこれらのマシンのIPまたは名前を指定せずに実行します。



Macにはdns-sdユーティリティ(またはmDNSの古いバージョン)があり、ネットワークサービスとその発見の発表に従事しています。 つまり いくつかのキーで開始され、彼女は「このコンピューターはこれを行うことができます」と言います。



方法は次のとおりです。



サービスは名前で指定され、サービス名はUnicode文字列( UTF-8形式)、最大63バイト(文字ではない)、 " _app-proto._tcp "または " _app-proto._udp "の形式で設定されます。サービスの名前です)「 app-proto 」は特別なサイトに登録する必要がありますが、ユーティリティは任意の値を取るため、このステップは不要です。



一般に、キー「-R」を指定してdns-sdを実行すると、ネットワークに新しいサービスが登録されます。



新サービス








「-B」キーを使用して同じコマンドを実行することにより、ネットワーク上で検索できます。



作成されたサービスを探しています








ご覧のように、サービス名に加えて、他のパラメーターがありますが、実際には「Hello!」行に加えて、興味深いものは何もありません。これらはこの実装には影響しません。 この行の「こんにちは」の代わりに、もっと便利なものを書くことができます。 サービスと転送されたファイルのチェックサムを発表したIPマシンに関する情報を書き留めます。



コードのビット。



これは私のコードではサーバーのアナウンスがどのように見えるかです:

#             dns-sd #         — dns-sd,    function _ClearServer { ps -f | awk"\$2==$1 && /_bolk-fileshare._tcp/ { print \$2 }" | xargs kill } dns-sd -R "$myownip $checksum" "_bolk-fileshare._tcp" . 1 >/dev/null & trap "_ClearServer $!" EXIT
      
      





ご覧のとおり、バックグラウンドでサービスのアナウンスを開始し、ユーティリティの終了時にバックグラウンドで実行されているdns-sdを打ちました。 バックグラウンドで起動を使用しない場合、スクリプトの実行はその場所で停止します-起動後のdns-sdは制御を返さず、終了すると、発表されたものからサービスを削除します。



今、サービスの発見。 このモードでは、 dns-sdトップユーティリティに似ています-コンソールもリリースされず、アナウンスおよびアナウンス解除されたサービスに関するイベントが画面に表示されます。 したがって、 expectユーティリティを使用する必要がありました。これは、このような場合に非常に便利です。



  local info=($(expect <<CMDS | awk 'NR>2 {print $7 " " $8}' | sort -u | tr -d '\r' | head -n1 spawn -noecho dns-sd -B _bolk-fileshare._tcp expect Timestamp expect -- "_bolk-fileshare._tcp" exit CMDS))
      
      







ここでの意味は次のとおりです。dns-sdにサービスの名前の行が表示されたら、制御を返すことを期待します。 その後、必要なものを選択します。サーバーのIPアドレスと送信されたファイルのチェックサムが転送されるまさにその行です。 info変数では、合計とIPという2つの要素の配列を取得します



残りはあまりおもしろくありません。結果のコード GitHubにあります。指定されたアドレスに接続し、 netcatユーティリティでファイルを取得します。



要約すると、アイデアは次のとおりです。対戦相手を検索するネットワークゲームは、特定の名前のサービスをアナウンスし、同時にアナウンスされたサービスをスキャンして、プレイしたいプレイヤーに尋ねます。 プレイヤーが誰かを選択すると、マシンが指定されたアドレスに接続され、ゲームが開始されます。



All Articles