j3259の日記: Java で ソケット
Sun - Writing the Server Side of a Socket
ServerSocket オブジェクトを作った瞬間からネットワークレイヤーではリクエストを受け付け始め、accept() メソッドで一つ一つを処理していくというコードになる。accept を次々呼び出さなくても行列を作ってちゃんと待っててくれるらしい。デフォルトは五十リクエストまで。
本来はリクエストが来るたびに新しいスレッドオブジェクトを作って次々処理していくという風に実装するわけだけど、これをやると FIFO 順序(first-in, first-out) ができないことになる。例えば、食堂にてチャーシュー麺と日替わり定食(豚の角煮)があるとして、チャーシュー麺は茹でたり盛り付けたりで五分かかるとして、日替わり定食の方は既に角煮を作り置きしてるからコロッケ、サラダとご飯と一緒に出して一分で準備ができるとする。さて、一人客が三人やってきて、「チャーシュー」、「日替わり」、「日替わり」と注文するとする。スタッフが何人もいるか、手際が良いとそれぞれの注文を並列(パラレル)に処理して一分後には日替わり定食の客二人、五分後にはチャーシュー麺の客の注文が運ばれる。
最初に来た客が最後に注文が運ばれるため、FIFO 順序は守られていない。
食堂の注文の場合はそれぞれのリクエストが独立してるため因果性が問題になることはないが、銀行の預金の引き出しのような場合はそうもいかない。ベクトル時計のような方法を使ってバージョン付けをするか、一つ一つ律儀に FIFO で処理する。つまり、手際の悪いスタッフが一人しかいないことにして、まず最初の客のチャーシュー麺を作って出す、次に日替わり、次に日替わりというふうになる。
public void listen() throws IOException {
while (true) {
// block the next request while I am working on this one
processRequest(m_serverSocket.accept());
} // while
}
private void processRequest(Socket a_socket) throws IOException {
PrintWriter out = new PrintWriter(a_socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(
new InputStreamReader(a_socket.getInputStream()));
String inputLine = in.readLine();
String outputLine;
if (inputLine.equals("hello")) {
outputLine = "hello back";
} else {
outputLine = "huh?";
} // if-else
out.println(outputLine);
out.close();
in.close();
a_socket.close();
}
}
上記のコードは "hello" と来たら "hello back"、その他の場合は "huh?" と返すだけ。
後は、そこをもっと複雑にしていくだけだから特にネットワークを意識する必要はない。
KnockKnockProtocol.javaを参考にしつつメッセージを String に変換して、逆に String からメッセージに戻すクラスを書く。
Java で ソケット More ログイン