待ち受け中のソケット

JavaでもC#でも良いが、仮にJavaだと仮定して、口をあけてメッセージを持ち受けているスレッドのソケットに対して、同期した処理を実施したい場合はどうすれば良いだろう。

class ReceiveThread extends Thread {
    Socket sc;
    public ReceiveThread(Socket sc) {
        this.sc= sc;
    }
    public void run() {
        try {
            while(!this.sc.isClosed()) {
                doReceive(this.sc.getInputStream());                     
            }
        } catch(IOException e) {
            System.out.println(e);
        }
    }
    private doReceive(InputStream is) {
        //データ受信処理
    }
}
Socket socket = new Socket();
socket.connect(address);
ReceiveThread rt = new ReceiveThread(socket);
rt.start();
〜

ループに入った後はSocket#getInputStreamメソッドがブロックしており、インバウンドメッセージを処理するdoReceiveメソッドは何時呼ばれるか解らない。
ここで対象のソケットに対して、sendAndReceiveのような送受信を同期して行う処理も実行させたいのだ。

public InputStream sendAndReceive(byte[] sendMessage) throws IOException {
    OutputStream os = this.sc.getOutputStream();
    os.write(sendMessage); //メッセージを書き込む
    return this.sc.getInputStream();
}

となると手は、

・スレッドを一度中止してソケットもろとも作り直す
・メッセージを送信した直後に受信メッセージが到着したか否かをポーリングする


だが、どちらも嫌だな。※ ソケットの制御を一時的に奪えないだろうか。

※.NETだと非同期デリゲートを使ってある程度スマートに書けそうだ。

追記
セマフォを使ってちびちびと試していたが、コメントで情報を頂いたxSocketというNIOベースのソケットライブラリィがいい感じだ。
xSocket

これなんて正に用途にぴったりな感じだ。
Tutorial connection-oriented applications - xSocket

5. Wrap a non-blocking connection by a blocking connection
xSocket's implementation of the BlockingConnection uses internally a INonBlockingConnection instance. That means, a BlockingConnection is a wrapper which brings in the blocking behaviour of the read methods. 〜

時間を空けて、試してみよう。