- PR -

SocketChannelを使用してのローカルアドレスとポートの指定方法

1
投稿者投稿内容
まさあき
会議室デビュー日: 2004/05/07
投稿数: 8
投稿日時: 2004-05-07 18:03
いつもお世話になっております。

SocketChannelとSelectorを使用して、サーバーとソケット通信を非同期で行うクライアントプログラムを作成しています。
サーバーからのデータ受信の際に、クライアント側で指定したローカルアドレスとポート番号にバインドさせたいのですが方法がわからず困っています。
java.net.Socketのコンストラクタにはそれらしきものが用意されていますが、SocketChannelを使用した場合の実現方法についてご教授ください。

以下、SocketChannelを使用してのソケット接続部分です。


public boolean connect() {

boolean result = true;

try {
// ソケットを生成
SocketChannel channel = SocketChannel.open();

// セレクタを生成
Selector selector = Selector.open();

// コネクト(サーバーのアドレスとポート番号を指定)
InetSocketAddress address = new InetSocketAddress(InetAddress.getByName(m_address), m_port);
channel.connect(address);

// コネクションがはれたら、ノンブロッキングモードに変更
channel.configureBlocking(false);

// セレクタにリードを登録
channel.register(m_selector, SelectionKey.OP_READ);

} catch (Exception e) {
e.printStackTrace();
result = false;
}

return result;
}
シュン
ぬし
会議室デビュー日: 2004/01/06
投稿数: 328
お住まい・勤務地: 東京都
投稿日時: 2004-05-09 04:14
SocketChannel#open()は、SelectorProvider#openSocketChannel()を呼んでいるだけです。
デフォルトのSelectorProviderが戻すSocketChannelは、すでにバインド操作が終わっている
状態のようですね。

未バインドのソケットが欲しい場合は、そのような状態のSocketChannel実装を作成するオリ
ジナルのSelectorProviderを自作し、java.nio.channels.spiのインプリメンテーションと
して登録し、デフォルトのSelectorProviderの代わりにそのオリジナルSelectorProviderを
使うよう設定してやる必要があるようです。

SocketChannelのAPIの構成からみるに、おそらく"クライアント側ソケットについては、
そのとき空いているローカルのポートのいずれかを使えばよいのであって、特にバインド対象
ポートをユーザが指定する必要はないはず"という思想で作られているものと思います。
どうしてもそうする必要があるということがなければ、逆らわないで使う方が良いのではない
でしょうか^^;

[ メッセージ編集済み 編集者: シュン 編集日時 2004-05-09 04:21 ]
まさあき
会議室デビュー日: 2004/05/07
投稿数: 8
投稿日時: 2004-05-09 21:04
自己レスです。
SocketChannel#open()後、socket()メソッドで取得したソケットオブジェクトにバインドすることで実現することが出来ました。

public boolean connect() {

boolean result = true;

try {
// ソケットを生成
SocketChannel channel = SocketChannel.open();

// セレクタを生成
Selector selector = Selector.open();

// コネクト(サーバーのアドレスとポート番号を指定)
InetSocketAddress address = new InetSocketAddress(InetAddress.getByName(m_address), m_port);

// ローカルアドレスとポート番号を指定
InetSocketAddress myaddress = new InetSocketAddress(InetAddress.getByName("my-server"), 4500);

// ローカルアドレスとポート番号をバインドする
channel.socket().bind(myaddress);

channel.connect(address);

// コネクションがはれたら、ノンブロッキングモードに変更
channel.configureBlocking(false);

// セレクタにリードを登録
channel.register(m_selector, SelectionKey.OP_READ);

} catch (Exception e) {
e.printStackTrace();
result = false;
}

return result;
}
1

スキルアップ/キャリアアップ(JOB@IT)