- 締切済み
SelectorとSocketChannelの使い方について分からない
SelectorとSocketChannelの使い方について分からない事があり困っております。 JavaのSelectorを利用した多重I/Oの色々なHPのサンプルプログラムを拝見したのですが全て「特定のサーバーに接続してそこにあるSelectorにSochetChannelをregisterして登録し、そこでそのまま送受信を行う」タイプのものでした。 私が今考えているのは「特定のサーバーに最初は接続するが、そこから複数のチャンネルがあり、その各チャンネルにはSelectorがあり、最初に接続したサーバーでSocketChannelを抽出するところまで行ってそれを各チャンネルのSelectorに渡してそこでregisterをする」というタイプです。こうするとデータの受信は最初に接続したサーバーが反応するのではなく、登録したSelectorのチャンネルが反応します。具体例を挙げると無作為で誰かとチャットが出来るようなサービスで、ただし回線切断からの再接続の場合は自動的に切断前に接続していたチャンネルへ再接続をしてくれる、というタイプのプログラムです。 そこで困っているのが「切断された後の再接続処理」についてです。 例えばチャンネル5番に接続されたとして何らかの原因で切断されるとします。その後再接続を行うと自動的にチャンネル5にログインするようにしたいのです。 しかし、接続して「再接続かどうか、また再接続ならどこのチャンネルに飛ばせばいいか」という情報をサーバーが受信するためにはまずSelectorにSocketChannelを登録しなければなりません。なので動作としては「サーバーのSelectorにSocketChannelを登録→データ受信→再接続先へ再接続、という処理になるかと思うのですが、こうすると「サーバーのSelectorからいったんSocketChannelを除いて特定のチャンネルのSelectorに登録しなおす」事になり、サーバーのSelectorから抜けた瞬間にサーバーからの接続が切断されてしまいます。 そこで「データを受信する前、つまり接続検知がありSelectorに登録するまでに再接続かどうかを判断しようと試みたのですが、接続検知で入手できるものはSelectionKeyとSocketChannelぐらいで、この二つをtoString()で文字列出力するとIP情報などが出てきたのですが再接続であるかどうかを判断するデータはありませんでした。 上記のように「サーバーに接続→初回接続ならサーバーから適当なチャンネルに飛ぶ→そのチャンネルとデータの送受信→接続が切断される→サーバーに再接続→サーバーが切断されたチャンネルに自動的に飛ばしてくれる」というプログラムは不可能なのでしょうか? 以上宜しくお願い致します。
- みんなの回答 (2)
- 専門家の回答
みんなの回答
- askaaska
- ベストアンサー率35% (1455/4149)
こういうのはどうかしら。 仮ログイン先:各クライアントは最初ここに接続する。 その接続を維持したまま各チャンネルに接続する。 ムリかな?
- askaaska
- ベストアンサー率35% (1455/4149)
ちょっとやったことのない分野なので アイデア的な回答でゴメンね。 自分がこれから行う接続が再接続かどうかって クライアント側は知っているんじゃないかしら? つまり前回接続したかどうか?とか チャットならユーザが「再接続を要求する」とか もしくは前回切断時から120秒以内の接続とか。 判断できる材料はあるじゃないかなと思うの。 どうかしら。
補足
お返事ありがとうございます。 私も現時点で、クライアント側は「さっき切断されたから次は再接続」というのは分かるのですが、それを受信するサーバーからすると「また新しいユーザーが接続してきた」という理解でしかありません。 サーバー側が「こいつはさっきチャンネル5に居て切断されたユーザーだ、チャンネル5に接続しなおし」という処理をしたいと考えております。しかし「チャンネル5に居たユーザーだ」という情報を得るために既にどこかのチャンネルに仮ログインをしなければいけません。そうなると「接続先の切り替え」をする必要が出てきてそれをしようとすると仮ログイン先から一時切断して新しいところへ接続するので切断した瞬間に端末とのセッションが切れてしまう、という状況です。
補足
お返事ありがとうございます。 その方法を現在模索しているのですが上手い方法が見つかっていない状態です。 ただし普通に考えますと「接続を維持したまま他のチャンネルにも接続する」と言う事は二重に接続していることになり、例えば「おはよう」とかデータを送信した場合どちらが受信するのか、または両方が受信するのかという不具合が発生します。また「端末から接続を2回試みて接続が二重になる」のならともかく、「1回の接続でセッションを二重に確立する」というのは恐らく理論的に無理な気がします。