スマフォアプリ(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;
}
}
}
次はサーバの機能強化を行います
戻る