スマフォアプリ(java/kotlin/Swift/Unity)からサーバ(java)のmariadbを操作する.4




●前提

同時接続は多数
サーバ言語:java+mariaDB+JDBCドライバ
MySQLのrootユーザー名root,passwordは1234abcde
クライアント言語:android-java/android-kotlin/iOS-Swift/unityC#
通信ポート:3456




今回はサーバのJavaの強化をします。
新規のスコアと名前の登録、指定された順位から指定した人数分のスコアと名前の取得です。
csvのパーサですが、javaなら.split()、C++ならboostとかでcsvパーシングしても良かったのですが、今回必要な物は単純な物なので手で組んだ物と、splitで分割した物の2通りが入っていますが、正規表現でエラーチェックしているのでsplitだけで良いと思います。あくまでも例です。

ScoreServerを起動した状態で無いとScoreClientは実行できません。
ScoreClientのコンパイルは、
javac ScoreClient.java
で、実行は、
java ScoreClient
で変更はありません。ScoreServerの方のコンパイルと実行は変わっていません。本来ならばファイルを分けないと行けませんが、サンプルなので一本で書きました。(classはたくさん使ってますが^^;)

[ScoerClient.java]


import java.net.Socket;
import java.net.ServerSocket;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.IOException;

public class ScoreClient {
    public static final String SERVER_URL = "219.117.194.51";         // うちの会社のIPアドレス。"localhost" とかでも実験は出来ます
    public static final int SOCKET_PORT = 3456;

    public static void main(String args[]) {

        Socket socket = null;

        try {
            System.out.println("接続します");
            socket = new Socket(SERVER_URL, SOCKET_PORT);
            System.out.println("接続しました" + socket.getRemoteSocketAddress());
            BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
            BufferedReader keyIn = new BufferedReader(new InputStreamReader(System.in));

            String input;

            System.out.println("1[enter]でユーザー情報をスコアの高い順から全部出力\n2,num1,num2[enter]でnum1番目からnum2人分出力\n3,nun,name[enter]で得点numでnameを登録\nただの[enter]で終了します。");

            while ( (input = keyIn.readLine()).length() > 0 ) {
                out.println(input);
                String line = in.readLine();
                if (line != null) {
                    if( input.equals("1")){
                        System.out.println("1が入力されました。ハイスコアを表示します");
                        System.out.println(line);
                    } else if( input.matches("2,[1-9][0-9]{0,},[1-9][0-9]{0,}") ){
                        System.out.println("2が入力されました。指定された順位から指定された人数分のスコアを表示します");
                        System.out.println(line);
                    } else if( input.matches("3,[1-9][0-9]{0,},[^ ]{1}.{1,999}") ){
                        System.out.println("3が入力されました。スコアを登録しました");
                        System.out.println(line);
                    } else {
                        System.out.println(line);
                    }
                } else {
                    System.out.println("[enter]だけが入力されたので終了します");
                    break;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (socket != null) {
                    socket.close();
                    socket=null;
                }
            } catch (IOException e) {}
            if(socket!=null) System.out.println("切断されました " + socket.getRemoteSocketAddress());
        }
    }
}
[ScoerServe.java]


import java.util.ArrayList;
import java.sql.*;
import java.net.Socket;
import java.net.ServerSocket;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.IOException;

//
// ハイスコアの管理サーバ(ctl+cで終了)
//
//----------------------------------------------------------------------------
class SqlCtl {
//
// sql control class
//
    static Connection con = null;
    private static final String MYSQL_URL = "jdbc:mysql://localhost:3306/test906";    // 接続するMySQLのURL(ローカルホスト:madiadb/MySQLは3306番ポート)
private static final String MYSQL_USR = "root"; // MySQLのユーザー名
private static final String MYSQL_PASS = "1234abcde"; // MySQLのユーザーのパスワード
// // MySQL(mariaDB)に接続 // public static boolean openSQL() { try { // mariaDBへ接続するためにJDBCドライバ読み込む Class.forName("org.mariadb.jdbc.Driver").newInstance(); // 接続する con = DriverManager.getConnection(MYSQL_URL, MYSQL_USR,MYSQL_PASS); System.out.println("MySQL(mariaDB)に接続できました"); return true; } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) { System.out.println("JDBCドライバのロードに失敗しました"); } catch (SQLException e) { System.out.println("MySQL(mariaDB)に接続できませんでした"); if (con != null) { try { con.close(); con=null; } catch (SQLException ex) { System.out.println("MySQL(mariaDB)のCloseに失敗しました"); } } } return false; } // // 値を返さないsqlクエリを実行 // private static boolean execUpdate(String sql) { try { Statement stm = con.createStatement(); stm.executeUpdate(sql); stm.close(); // close return true; } catch (SQLException e) { return false; } } // // スコア順に取得する(先頭に人数が入ります) // public static String getScoreRank( String outLines ) { try { // // データを取得するには Statement を作成して executeQuery() でSQL文を投げると ResultSet の object で返ってくる // Statement stm = con.createStatement(); ResultSet rs = stm.executeQuery("SELECT * FROM hiscore ORDER BY score DESC,id ASC"); String line=""; // rs.next()はこのカラムがあるかだけでは無く、次のカラムに移動させるので、このような方法をとっています。 int c=0; while(rs.next()){ c++; line += "," + "id:" + rs.getInt("id") + ":name=" + rs.getString("name") + ":score=" + rs.getInt("score"); } outLines = c + line; rs.close(); // close stm.close(); // close return outLines; } catch (SQLException e) { System.out.println("MySQL(mariaDB)に接続できませんでした3"); } return outLines; } // // 指定された順位から指定された人数分を、スコア順に取得する(スコアと名前だけをcsv形式で、先頭に人数が入ります) // public static String getScoreRankNum( String outLines,int top,int count ) { // top(1org)からcount(1org)分取得する。 if( (top<1) || (count<1) ){ outLines="0"; return outLines; } try { // // データを取得するには Statement を作成して executeQuery() でSQL文を投げると ResultSet の object で返ってくる // Statement stm = con.createStatement(); ResultSet rs = stm.executeQuery("SELECT * FROM hiscore ORDER BY score DESC,id ASC"); String line=""; // rs.next()はこのカラムがあるかだけでは無く、次のカラムに移動させるので、このような方法をとっています。 int c=0; int outCount=0; while(rs.next() && count!=0 ){ c++; if(c>=top){ line += "," + rs.getInt("score") + "," + rs.getString("name"); count--; outCount++; } } outLines = outCount + line; rs.close(); // close stm.close(); // close return outLines; } catch (SQLException e) { System.out.println("MySQL(mariaDB)に接続できませんでした3"); } return outLines; } // // スコアと名前をデータベースに登録 // public static void insertScore( int score, String name) { String insert = "INSERT INTO hiscore (name,score) VALUES('" + name + "'," + score + ")"; if(!execUpdate(insert)){ System.out.println("追加出来ませんでした"); } } /* // // だれもデータベースに登録されていない場合、とりあえず一人分追加します、 // private static void initScore() { if(!execUpdate("INSERT INTO hiscore (name,score) VALUES('けんぢ',1)")){ System.out.println("追加出来ませんでした"); } } */ } //---------------------------------------------------------------------------- class MiniCSV { // // 簡短なcsvをArrayListにするクラス(簡易版) // private static final char SEPARATOR = ','; public static int getCSV(ArrayList csvData,String str){ char tmp; char SEPARATOR = ','; int csvCount = 0; int strCount = 0; int strLen = str.length(); while(strLen>strCount){ StringBuffer sb = new StringBuffer(); while(strLen>strCount){ tmp = str.charAt(strCount); strCount++; if(tmp==SEPARATOR) break; sb.append(tmp); } csvCount++; csvData.add(sb.toString()); } return csvCount; } } //---------------------------------------------------------------------------- // // ソケットサーバとマルチスレッドでの待ち受け(ctl+cで終了) // class MultiSocket { public static final int SOCKET_PORT = 3456; public static boolean socketMain() { // serversocket ServerSocket serverSocket = null; try { serverSocket = new ServerSocket(SOCKET_PORT); System.out.println("サーバーが起動しました(port="+ serverSocket.getLocalPort() + ")"); System.out.println("サーバーを終了する場合は ctrl+c で終了させて下さい"); // 待ち受け(ctrl+cで終了) while (true) { Socket socket = serverSocket.accept(); // 待ち受け許可 new ScoreThread(socket).start(); // クライアントに接続されたらスレッド作成 } } catch (IOException e) { e.printStackTrace(); } finally { try { if (serverSocket != null) { serverSocket.close(); serverSocket = null; } } catch (IOException e) {} } return false; } } //---------------------------------------------------------------------------- // // スレッド // class ScoreThread extends Thread { private Socket socket; public ScoreThread(Socket socket) { this.socket = socket; System.out.println("接続されました " + socket.getRemoteSocketAddress()); } // run()は自動的に実行される public void run() { try { BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); PrintWriter out = new PrintWriter(socket.getOutputStream(), true); String line; while ( (line = in.readLine()) != null ) { System.out.println(socket.getRemoteSocketAddress() + " 受信:" + line); // クライアントから1が入力された場合はハイスコア表示 if(line.equals("1")){ line=""; line = SqlCtl.getScoreRank(line); out.println(line); System.out.println(socket.getRemoteSocketAddress() + " 送信:" + line); }else if(line.matches("2,[1-9][0-9]{0,},[1-9][0-9]{0,}") ){ // 正規表現をくぐり抜けているので、パラメータ(line)にエラーは無いものとする。 // オリジナルのcsvパーサを使った方 ArrayList csvData = new ArrayList(); MiniCSV.getCSV(csvData,line); line=""; line = SqlCtl.getScoreRankNum(line,Integer.parseInt(csvData.get(1)),Integer.parseInt(csvData.get(2))); out.println(line); System.out.println(socket.getRemoteSocketAddress() + " 送信:" + line); }else if(line.matches("3,[1-9][0-9]{0,},[^ ]{1}.{1,999}") ){ // 正規表現をくぐり抜けているので、パラメータ(line)にエラーは無いものとする。 // splitで分割した方 String[] csvData = line.split(","); line = "scoreが" + csvData[1] + "の" + csvData[2] + "さんを登録します"; SqlCtl.insertScore( Integer.parseInt(csvData[1]),csvData[2] ); out.println(line); System.out.println(socket.getRemoteSocketAddress() + " 送信:" + line); } else { out.println(line+"は間違ったコマンドです"); System.out.println(socket.getRemoteSocketAddress() + " 送信(error-cmd): " + line); } } System.out.println("クライアントは終了しました" + socket.getRemoteSocketAddress()); } catch (IOException e) { e.printStackTrace(); } finally { try { if (socket != null) { socket.close(); socket=null; } } catch (IOException e) {} if(socket!=null) { System.out.println("切断されました" + socket.getRemoteSocketAddress()); socket=null; } } } } //---------------------------------------------------------------------------- // // メイン // public class ScoreServer { public static void main(String[] args) { // データベースへ接続する if(!SqlCtl.openSQL()){ System.out.println("データベースに接続できませんでした"); return; } // マルチクライアントソケットサーバの起動 if(!MultiSocket.socketMain()){ System.out.println("マルチクライアントソケットサーバの起動に失敗しました"); return; } } }


次はandroid-javaからのアクセスとJAVAサーバ/JAVAクライアントの修正をします。


戻る