各クライアントを相手にするために,スレッドを作って対応するのが一般的で ある.以下に,簡単なサーバプログラムとして chat(おしゃべり)サーバを作っ てみている.
// 入出力ストリームを使うので,java.io.* を import import java.io.*; // ソケットを使うので java.net.* を import import java.net.*; // 一人のクライアントとの通信を担当するスレッド // スレッド上で走らせるため Runnable インタフェースを実装 class Worker implements Runnable{ // 通信のためのソケット Socket sock; // そのソケットから作成した入出力用のストリーム PrintWriter out; BufferedReader in; // サーバ本体のメソッドを呼び出すために記憶 ChatServer chatServer; // 担当するクライアントの番号 int n; // コンストラクタ public Worker(int n,Socket s,ChatServer cs){ this.n=n; chatServer=cs; sock=s; out=null; in=null; } // 対応するスレッドが start した時に呼ばれる. public void run(){ System.out.println("Thread running:"+Thread.currentThread()); try{ // ソケットからストリームの作成 out = new PrintWriter(sock.getOutputStream(),true); in = new BufferedReader(new InputStreamReader(sock.getInputStream())); String s=null; // ソケットからの入力があったら, while((s=in.readLine())!=null){ // クライアント全体に送る. chatServer.sendAll("["+n+"]"+s); } // 自分自身をテーブルから取り除く chatServer.remove(n); // ソケットを閉じる sock.close(); } catch(IOException ioe){ System.out.println(ioe); chatServer.remove(n); } } // 対応するソケットに文字列を送る public void send(String s){ out.println(s); } } public class ChatServer{ // 各クライアントを記憶する配列. Worker workers[]; // コンストラクタ public ChatServer(){ // ポート番号を 4444にする.同じマシンで同じポートを使うことは // できないので,ユーザごとに変えること(1023以下は使えない) int port=4444; // 配列を作成 workers=new Worker[100]; Socket sock; try{ // ServerSocketを作成 ServerSocket servsock=new ServerSocket(port); // 無限ループ,breakが来るまで while(true){ // クライアントからのアクセスをうけつけた. sock=servsock.accept(); int i; // 配列すべてについて for(i=0;i< workers.length;i++){ // 空いている要素があったら, if(workers[i]==null){ // Workerを作って workers[i]=new Worker(i,sock,this); // 対応するスレッドを走らせる new Thread(workers[i]).start(); break; } } if(i==workers.length){ System.out.println("Can't serve"); } } } catch(IOException ioe){ System.out.println(ioe); } } public static void main(String args[]) throws IOException{ // インスタンスを1つだけ作る. new ChatServer(); } // synchronized は,同期のためのキーワード.つけなくても動くことはある. public synchronized void sendAll(String s){ int i; for(i=0;i< workers.length;i++){ // workers[i]が空でなければ文字列を送る if(workers[i]!=null) workers[i].send(s); } } // クライアント n が抜けたこと記録し,他のユーザに送る. public void remove(int n){ workers[n]=null; sendAll("quiting ["+n+"]"); } }このプログラムをあるマシン(例 ux019上で)
java ChatServerと動かしておいて,他のマシン(ux019自身でも可)で,
telnet ux019 4444を実行すると,chatに参加できる.
ヒント
以下の2つのスレッドを作成するとシンプルに作成できます.