待ち受け中のソケット
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. 〜
時間を空けて、試してみよう。