diff --git a/src/j7/SeaGameClient.java b/src/j7/SeaGameClient.java index 0733896..3e24432 100644 --- a/src/j7/SeaGameClient.java +++ b/src/j7/SeaGameClient.java @@ -8,27 +8,45 @@ // // プログラムを停止するにはlogout ボタンを押す -import java.awt.*; // グラフィックス -import java.awt.event.*;// イベント関連 -import java.net.*; // ネットワーク関連 -import java.io.*; -import java.util.*; +// グラフィックス +import java.awt.BorderLayout; +import java.awt.Canvas; +import java.awt.Color; +import java.awt.Graphics; +import java.awt.GridLayout; +// イベント関連 +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.BufferedReader; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.InputStreamReader; +// ネットワーク関連 +import java.net.Socket; +import java.util.StringTokenizer; + +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextField; public class SeaGameClient implements Runnable { - Frame f;// クライアント情報表示用ウィンドウ - Panel p;// 上下左右の移動ボタンと海の状態を表示するパネル + JFrame f;// クライアント情報表示用ウィンドウ + JPanel p;// 上下左右の移動ボタンと海の状態を表示するパネル Canvas c;// 海の状態を表示するキャンバス //--------------------------------------------------------------------- // GUI 画面の初期配置 public SeaGameClient () { - Button b; - f = new Frame();//クライアント情報ウィンドウ全体の表示 - p = new Panel();//海表示部分と操作ボタンの表示 + JButton b; + f = new JFrame();//クライアント情報ウィンドウ全体の表示 + p = new JPanel();//海表示部分と操作ボタンの表示 p.setLayout(new BorderLayout()); // upボタンの作成 - b = new Button("up"); + b = new JButton("up"); b.addActionListener(new ActionListener(){ // upボタンが押されたらupコマンドを送信 public void actionPerformed(ActionEvent e){ @@ -38,7 +56,7 @@ p.add(b, BorderLayout.NORTH); // leftボタンの作成 - b = new Button("left"); + b = new JButton("left"); b.addActionListener(new ActionListener(){ // leftボタンが押されたらleftコマンドを送信 public void actionPerformed(ActionEvent e){ @@ -48,7 +66,7 @@ p.add(b, BorderLayout.WEST); // rightボタンの作成 - b = new Button("right"); + b = new JButton("right"); b.addActionListener(new ActionListener(){ // rightボタンが押されたらrightコマンドを送信 public void actionPerformed(ActionEvent e){ @@ -58,7 +76,7 @@ p.add(b, BorderLayout.EAST); // downボタンの作成 - b = new Button("down"); + b = new JButton("down"); b.addActionListener(new ActionListener(){ // downボタンが押されたらdownコマンドを送信 public void actionPerformed(ActionEvent e){ @@ -75,7 +93,7 @@ f.add(p); // フレームfにloginボタンの取り付け - b = new Button("login"); + b = new JButton("login"); b.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e){ // loginボタンが押された場合の処理 @@ -86,7 +104,7 @@ f.add(b,BorderLayout.NORTH); // フレームfにlogoutボタンの取り付け - b = new Button("logout"); + b = new JButton("logout"); b.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e){ logout(); @@ -100,13 +118,15 @@ } // end of SeaGameClient //-------------------------------------------------------------------- // runメソッド/ 500ミリ秒ごとに画面を更新 + Thread thread = null; public void run(){ - while (true){ + d.dispose(); + while (thread != null){ try { Thread.sleep(500); }catch(Exception e){ } - // repainメソッドを用いて,サーバ上の情報を画面に出力します + // repaintメソッドを用いて,サーバ上の情報を画面に出力します repaint(); } } // end of run @@ -114,27 +134,28 @@ // login処理関連のオブジェクト int sx = 100; int sy = 100; - TextField host, tf_name; - Dialog d; + JTextField host, tf_name; + JDialog d; //--------------------------------------------------------------------- // loginウィンドウを表示し,必要な情報を得る // 実際のlogin処理は,realLoginメソッド void login(){ // ウィンドウの表示とデータの入力 - d = new Dialog(f, true); - host = new TextField(10) ; - tf_name = new TextField(10) ; + d = new JDialog(f, true); + host = new JTextField("127.0.0.1",10) ; + tf_name = new JTextField("user",10) ; d.setLayout(new GridLayout(3,2)); - d.add(new Label("host:")); + d.add(new JLabel("host:")); d.add(host); - d.add(new Label("name:")); + d.add(new JLabel("name:")); d.add(tf_name); - Button b = new Button("OK"); + JButton b = new JButton("OK"); b.addActionListener(new ActionListener(){ // 入力が完了したら,readlLoginメソッドを使ってサーバにloginします public void actionPerformed(ActionEvent e){ realLogin(host.getText(), tf_name.getText()); + System.out.println("after reallogin"); d.dispose(); } }); @@ -142,31 +163,33 @@ d.setResizable(true); d.setSize(200, 150); d.setVisible(true); - (new Thread(this)).start(); + thread = new Thread(this); + thread.start(); } // end of login //--------------------------------------------------------------------- // realLogin関連のオブジェクト Socket server;// ゲームサーバとの接続ソケット - int port = 10000; // 接続ポート + int port = 9999; // 接続ポート BufferedReader in; // 入力ストリーム - PrintWriter out; // 出力ストリーム + DataOutputStream out; // 出力ストリーム String name; // ゲーム参加者の名前 //--------------------------------------------------------------------- // サーバへのログイン処理 void realLogin(String host, String name){ + System.out.println("realLogin "+host+" "+name); try { // サーバとの接続 this.name = name; server = new Socket(host, port); - in = new BufferedReader(new InputStreamReader( - server.getInputStream())); - out = new PrintWriter(server.getOutputStream()); + in = new BufferedReader(new InputStreamReader(server.getInputStream())); + out = new DataOutputStream(server.getOutputStream()); + Thread.sleep(1000); // loginコマンドの送付 - out.println("login " + name); - out.flush(); - repaint(); + out.writeBytes("login " + name+"\n"); + System.out.println("sent login name "+name); + // repaint(); } catch(Exception e) { e.printStackTrace(); System.exit(1); @@ -177,7 +200,7 @@ void logout(){ try { // logoutコマンドの送付 - out.println("logout"); + out.writeBytes("logout"); out.flush(); server.close(); }catch (Exception e){ @@ -189,8 +212,12 @@ // サーバからゲームの情報を得て,クライアントの画面再描画 void repaint(){ // サーバにstatコマンドを送付し,盤面の様子などの情報を取得 - out.println("stat"); - out.flush(); + try { + out.writeBytes("stat"); + out.flush(); + } catch (IOException e1) { + e1.printStackTrace(); + } try { String line = in.readLine();// サーバからの入力の読み込み @@ -222,7 +249,7 @@ int x = Integer.parseInt(st.nextToken()) ; int y = Integer.parseInt(st.nextToken()) ; - + g.fillOval(x - 10, 256 - y - 10, 20, 20); // 船を表示 g.drawString(st.nextToken(),x+10,256-y+10) ; // 得点を船の右下に表示 g.drawString(obj_name,x+10,256-y-10) ; // 名前を船の右上に表示 @@ -259,16 +286,21 @@ //--------------------------------------------------------------------- // サーバへコマンドを送信 void sendCommand(String s){ - if ("up".equals(s)){ - out.println("up"); - }else if ("down".equals(s)){ - out.println("down"); - }else if ("left".equals(s)){ - out.println("left"); - }else if ("right".equals(s)){ - out.println("right"); + System.out.println(s); + try { + if ("up".equals(s)){ + out.writeBytes("up"); + }else if ("down".equals(s)){ + out.writeBytes("down"); + }else if ("left".equals(s)){ + out.writeBytes("left"); + }else if ("right".equals(s)){ + out.writeBytes("right"); + } + out.flush(); + } catch (IOException e) { + e.printStackTrace(); } - out.flush(); } // mainメソッド diff --git a/src/j7/SeaGameServer.java b/src/j7/SeaGameServer.java index 31beed4..2eecb90 100644 --- a/src/j7/SeaGameServer.java +++ b/src/j7/SeaGameServer.java @@ -6,41 +6,42 @@ // 起動すると,ポート番号10000 番に対するクライアントからの接続を待ちます // プログラムを停止するにはコントロールC を入力してください import java.io.BufferedReader; +import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStreamReader; -import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; +import java.util.ArrayList; import java.util.Hashtable; import java.util.Random; import java.util.StringTokenizer; import java.util.Vector; public class SeaGameServer { - static final int DEFAULT_PORT = 10000; - //SeaGameServer接続用ポート番号 + static final int DEFAULT_PORT = 9999; + //SeaGameServer接続用ポート番号 static ServerSocket serverSocket; - static Vector connections; - //クライアントとのコネクションを保持するVectorオブジェクト + static ArrayList clientprocs; + //クライアントとのコネクションを保持するVectorオブジェクト static Vector energy_v; // 燃料タンクの位置情報リスト static Hashtable userTable = null; - // クライアント関連情報登録用テーブル + // クライアント関連情報登録用テーブル static Random random = null; // addConnectionメソッド // クライアントとの接続をVectorオブジェクトconnectionsに登録します - public static void addConnection(Socket s){ - if (connections == null){//初めてのコネクションの場合は, - connections = new Vector();// connectionsを作成します + public static void addConnection(ClientProc s){ + if (clientprocs == null){//初めてのコネクションの場合は, + clientprocs = new ArrayList();// connectionsを作成します } - connections.addElement(s); + clientprocs.add(s); } // deleteConnectionメソッド // クライアントとの接続をconnectionsから削除します - public static void deleteConnection(Socket s){ - if (connections != null){ - connections.removeElement(s); + public static void deleteConnection(ClientProc s){ + if (clientprocs != null){ + clientprocs.remove(s); } } @@ -137,26 +138,26 @@ // STATコマンドを処理 // クライアントに船の情報(ship_info)と, // 海上を漂流している燃料タンクの情報を(energy_info)を送信 - public static void statInfo(PrintWriter pw){ + public static void statInfo(DataOutputStream pw) throws IOException{ // 船の情報(ship_info)の送信 - pw.println("ship_info"); + pw.writeBytes("ship_info"); if (userTable != null){ for (String user : userTable.keySet()) { Ship ship = (Ship) userTable.get(user); - pw.println(user + " " + ship.x + " " - + ship.y + " " + ship.point); + pw.writeBytes(user + " " + ship.x + " " + + ship.y + " " + ship.point); } } - pw.println(".");// ship_infoの終了 + pw.writeBytes(".");// ship_infoの終了 // 燃料タンクの情報(energy_info)の送信 - pw.println("energy_info"); + pw.writeBytes("energy_info"); if (energy_v != null){ // すべての燃料タンクの位置情報をクライアントに送信します for (int[] e : energy_v) { - pw.println(e[0] + " " + e[1]); + pw.writeBytes(e[0] + " " + e[1]); } } - pw.println(".");// enegy_infoの終了 + pw.writeBytes(".");// enegy_infoの終了 pw.flush(); } //--------------------------------------------------------------------- @@ -205,10 +206,9 @@ while (true) {// 無限ループ try { Socket cs = serverSocket.accept(); - addConnection(cs);// コネクションを登録します // クライアント処理スレッドを作成します - Thread ct = new Thread(new clientProc(cs)); - ct.start(); + ClientProc cp = new ClientProc(cs); + addConnection(cp);// ClientProcを登録します }catch (IOException e){ System.err.println("client socket or accept error."); } @@ -216,73 +216,81 @@ } // end of main } // end of class putEnergy //============================================================================= -class clientProc implements Runnable { +class ClientProc implements Runnable { + Thread thread; Socket s; // クライアント接続用ソケット BufferedReader in; // 入力ストリーム - PrintWriter out; // 出力ストリーム + DataOutputStream out; // 出力ストリーム String name = null; // クライアントの名前 //-------------------------------------------------------------------- // ソケットを使って入出力ストリームを作成します - public clientProc(Socket s) throws IOException { + public ClientProc(Socket s) throws IOException { this.s = s; - in = new BufferedReader(new InputStreamReader( - s.getInputStream())); - out = new PrintWriter(s.getOutputStream()); + in = new BufferedReader(new InputStreamReader(s.getInputStream())); + out = new DataOutputStream(s.getOutputStream()); + thread = new Thread(this); + thread.start(); } //-------------------------------------------------------------------- public void run(){ - try { - //LOGOUTコマンド受信まで繰り返します - while (true) { - // クライアントからの入力を読み取ります - String line = in.readLine(); - // nameが空の場合にはLOGINコマンドのみを受け付けます - if (name == null){ - StringTokenizer st = new StringTokenizer(line); - String cmd = st.nextToken(); - if ("login".equalsIgnoreCase(cmd)){ - name = st.nextToken(); - SeaGameServer.loginUser(name); - }else{ - // LOGINコマンド以外は無視 - } - }else{ - // nameが空でない場合はログイン済み.コマンドを受け付ける. - StringTokenizer st = new StringTokenizer(line); - String cmd = st.nextToken();// コマンドの取り出し - // コマンドに対応する処理 - if ("STAT".equalsIgnoreCase(cmd)){ - SeaGameServer.statInfo(out); - } else if ("UP".equalsIgnoreCase(cmd)){ - SeaGameServer.up(name); - } else if ("DOWN".equalsIgnoreCase(cmd)){ - SeaGameServer.down(name); - } else if ("LEFT".equalsIgnoreCase(cmd)){ - SeaGameServer.left(name); - } else if ("RIGHT".equalsIgnoreCase(cmd)){ - SeaGameServer.right(name); - } else if ("LOGOUT".equalsIgnoreCase(cmd)){ - SeaGameServer.logoutUser(name); - // LOGOUTコマンドの場合には繰り返しを終了 - break; - } - } - } - // 登録情報を削除し,接続を切断 - SeaGameServer.deleteConnection(s); - s.close(); - } catch (IOException e) { + //LOGOUTコマンド受信まで繰り返します + while(thread != null) { + String line; + System.out.println("running " + name); try { - s.close(); - } catch (IOException e2){} + while ((line = in.readLine()) != null) { + // クライアントからの入力を読み取ります + System.out.println(line); + // nameが空の場合にはLOGINコマンドのみを受け付けます + if (name == null){ + StringTokenizer st = new StringTokenizer(line); + String cmd = st.nextToken(); + if ("login".equalsIgnoreCase(cmd)){ + name = st.nextToken(); + System.out.println(name); + SeaGameServer.loginUser(name); + }else{ + // LOGINコマンド以外は無視 + } + } else { + // nameが空でない場合はログイン済み.コマンドを受け付ける. + System.out.println(line); + StringTokenizer st = new StringTokenizer(line); + String cmd = st.nextToken();// コマンドの取り出し + // コマンドに対応する処理 + if ("STAT".equalsIgnoreCase(cmd)){ + SeaGameServer.statInfo(out); + } else if ("UP".equalsIgnoreCase(cmd)){ + SeaGameServer.up(name); + } else if ("DOWN".equalsIgnoreCase(cmd)){ + SeaGameServer.down(name); + } else if ("LEFT".equalsIgnoreCase(cmd)){ + SeaGameServer.left(name); + } else if ("RIGHT".equalsIgnoreCase(cmd)){ + SeaGameServer.right(name); + } else if ("LOGOUT".equalsIgnoreCase(cmd)){ + SeaGameServer.logoutUser(name); + // LOGOUTコマンドの場合には繰り返しを終了 + break; + } + } + System.out.println("end"); + } + } catch (IOException e) { + e.printStackTrace(); + } finally { + // 登録情報を削除し,接続を切断 + SeaGameServer.deleteConnection(this); +// s.close(); + } } } // end of run } // enf of class clientProc //============================================================================= // 船の位置と,獲得した燃料タンクの数を管理 class Ship { - + int x, y; // 船の位置座標 int point = 0; // 獲得した燃料タンクの個数 diff --git a/src/run7-1.sh b/src/run7-1.sh index a316b25..af9c1a9 100755 --- a/src/run7-1.sh +++ b/src/run7-1.sh @@ -2,8 +2,8 @@ javac -encoding UTF-8 j7/*.java -echo "run SeaGameServer 6000" -java j7/SeaGameServer 6000 +echo "run SeaGameServer 9999" +java j7/SeaGameServer 9999 # java j4/MyFTP 127.0.0.1 diff --git a/src/run7-2.sh b/src/run7-2.sh new file mode 100755 index 0000000..15d441a --- /dev/null +++ b/src/run7-2.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +javac -encoding UTF-8 j7/*.java + +echo "run SeaGameClient" +java j7/SeaGameClient + + +# java j4/MyFTP 127.0.0.1 + +#echo "type return to exit" +#read input_str +