ソケットについて |
以下に示すプログラムは、ソケットを介して、クライアントプログラムからサーバプ ログラムにコネクションを確立する方法を示した簡単な例である。 java.net パッケージの Socket クラスは、クライアントとサーバを結ぶ双方向通信 リンクのクライアント側の末端部を、プラットフォームに依存しないで実装するもの である。Socket クラスはプラットフォームに依存する実装の最上部に位置し、ユー ザの Java プログラムが特定のシステムに関する細かい部分を意識しないですむよう にする。ネイティブコードではなく java.net の Socket クラスを使用することによ って、 Java プログラムはプラットフォームに依存しない方式でネットワーク上で通 信することができる。
このクライアントプログラム、EchoTest は、ソケット経由で標準的な Echo サーバ に (ポート 7 で) 接続する。このクライアントはソケットからの読み取りとソケッ トへの書き込みを両方とも行う。EchoTest は標準入力に入力されたすべてのテキス トを、ソケットへの書き込みを通して Echo サーバに送る。 サーバはクライアントから受け取ったすべての入力を、ソケッ トを通してクライアントにエコーバックする。クライアントプログラムはサーバから 戻されたデータを読み取り、表示する。
import java.io.*; import java.net.*;public class EchoTest { public static void main(String[] args) { Socket echoSocket = null; DataOutputStream os = null; DataInputStream is = null; DataInputStream stdIn = new DataInputStream(System.in); try { echoSocket = new Socket("taranis", 7); os = new DataOutputStream(echoSocket.getOutputStream()); is = new DataInputStream(echoSocket.getInputStream()); } catch (UnknownHostException e) { System.err.println("Don't know about host: taranis"); } catch (IOException e) { System.err.println("Couldn't get I/O for the connection to: taranis"); } if (echoSocket != null && os != null && is != null) { try { String userInput; while ((userInput = stdIn.readLine()) != null) { os.writeBytes(userInput); os.writeByte('¥n'); System.out.println("echo: " + is.readLine()); } os.close(); is.close(); echoSocket.close(); } catch (IOException e) { System.err.println("I/O failed on the connection to: taranis"); } } } }このプログラムを丹念に観察し、重要な箇所を掘り下げてみる。
main() メソッドの最初の try ブロックの 3 行を次に 示す。これらは重要な行であり、クライアントとサーバの間のソケットコネクション を確立し、そのソケットで入力ストリームと出力ストリームを開いている。
echoSocket = new Socket("taranis", 7); os = new DataOutputStream(echoSocket.getOutputStream()); is = new DataInputStream(echoSocket.getInputStream());この並びでの最初の行は新規の Socket オブジェクトを作成し、それに echoSocket という名前を付けている。ここで使用される Socket コン ストラクタ (ほかにも 3 つある) では、接続させるマシンの名前とポート番号が必 須である。このプログラム例は、当社のローカルネットワークにある (仮の) マシン の名前である taranis をホスト名として使用しているが、このプログ ラムを読者のマシンで入力し実行する場合は、この名前を読者のネットワークにある マシンの名前に変更する必要がある。使用する名前は、接続させるマシンの完全修飾 された IP 名である。2 番目の引数はポート番号であり、ここでのポート番号 7 は Echo サーバが監視するポートである。
上記のコード片の 2 番目の行はソケットの出力ストリームを開き、3 番目の行はソ ケットの入力ストリームを開いている。EchoTest はこの出力ストリームに書き込み 、入力ストリームから読み取るだけで、ソケットを通してサーバと通信できるのであ る。プログラムの後半部でこれを行う。入力ストリームと出力ストリームについてま だよく理解できていない場合は、 入出力ストリーム を読むことをお勧めする。
コードの次のセクションは、EchoTest の標準入力 (ユーザがデータを入力できる場 所) から一度に 1 行ずつを読み取る。EchoTest は入力テキストの後に改行文字を付 けて、ただちに、ソケットに接続されている出力ストリームへ書き込んでいる。
String userInput; while ((userInput = stdIn.readLine()) != null) { os.writeBytes(userInput); os.writeByte('¥n'); System.out.println("echo: " + is.readLine()); }while ループの最後の行は、ソケットに接続された入力ストリームか ら1 行の情報を読み取っている。readLine() メソッドは、サーバが情 報を EchoTest にエコーバックするまでブロックする。readline() が 戻ると、EchoTest は標準出力に情報を出力する。
このループは、EchoTest がユーザからの入力を読み取り、それを Echo サーバに送 信し、サーバから応答を得て、それを表示する、という動作を、ユーザが入力終了文 字を入力するまで繰り返す。
ユーザが入力終了文字を入力すると while ループは終了し、プログ ラムは次の 3 行のコードの実行に移る。
os.close(); is.close(); echoSocket.close();これらのコード行は整理のカテゴリに入る。良いプログラムとは常に、それ自身の後 処理をきちんとするものである。その意味で、このプログラムは良いプログラムであ る。 この 3 行はソケットに接続された入力および出力ストリームを閉じ、サーバへのソ ケットコネクションを閉じている。この順序は重要であり、必ず、ソケットに接続さ れたストリームをすべて閉じてから、ソケット自体を閉じるようにする。
このクライアントプログラムは、Echo サーバが単純なプロトコルを実装しているた め、わかりやすく簡単である。クライアントがサーバにテキストを送り、サーバがそ れをエコーバックするだけである。読者のクライアントプログラムが http サーバの ような複雑なサーバと情報をやり取りする場合は、クライアントプログラムももっと 複雑になる。 ただし基本部分は、このプログラムとほとんど同じである。
- ソケットを開く。
- ソケットに対する入力ストリームと出力ストリームを開く。
- サーバのプロトコルに従ってストリームを読み書きする。
- ストリームを閉じる。
- ソケットを閉じる。
手順 3 だけは、サーバによって、クライアントごとに異なる。 その他の手順はかなりの部分が同じである。
ソケットについて |