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




●前提

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



では、firewall-cmdでポートの開放をしましょう。3456番ポートですね。
# firewall-cmd --zone=public --add-port=3456/tcp --permanent
# firewall-cmd --reload

今回はSQLにサーバのJavaから代理でクエリを出して、その結果を得るだけなので、マルチスレッドにする必要性はそれほどありませんが、今後のためにマルチスレッド化します。
これを発展させればチャットやロビー、ゲームサーバ、在庫管理サーバなども作れると思いますが、C#のREFとかポインタ渡しが出来ない言語だときついですね。
スコアの順序は高い人からでカンマで区切って出力しています。csv形式ですね。

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]でハイスコアを、ただの[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 {
                        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.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"); // rs.next()はこのカラムがあるかだけでは無く、次のカラムに移動させるので、このような方法をとっています。 boolean f=false; while(rs.next()){ f=true; int id = rs.getInt("id"); String name = rs.getString("name"); int score = rs.getInt("score"); outLines += "id:" + id + ":name=" + name + ":score=" + score + ","; } if(f==false){ System.out.println("データがありませんので一人分追加します"); initScore(); } rs.close(); // close stm.close(); // close return outLines; } catch (SQLException e) { System.out.println("MySQL(mariaDB)に接続できませんでした3"); } return outLines; } // // だれもデータベースに登録されていない場合、とりあえず一人分追加します、 // private static void initScore() { if(!execUpdate("INSERT INTO hiscore (name,score) VALUES('けんぢ',1)")){ System.out.println("追加出来ませんでした"); } } } //---------------------------------------------------------------------------- // // ソケットサーバとマルチスレッドでの待ち受け(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 { 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; } } }


次はサーバの機能強化を行います


戻る