Newer
Older
ServerTester / src / main / java / info / istlab / ServerTester / Server.java
package info.istlab.ServerTester;

import java.io.IOException;
import java.net.BindException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;

import javax.swing.JOptionPane;

public class Server implements Runnable {
    public ServerSocket serverSocket;
    Thread thread;
    int expectedPort;
    String expectedAddress;
    boolean bindFailed = false;

    public static void invokeMain(String[] args, String className) {
        try {
            if (args.length == 0) {
                Class.forName("info.istlab.ServerTester." + className).getConstructor().newInstance();
            } else if (args.length == 1) {
                if (isNumeric(args[0])) { // 数値の場合はポート番号として扱う
                    Class.forName("info.istlab.ServerTester." + className).getConstructor(int.class)
                            .newInstance(Integer.parseInt(args[0]));
                } else { // 数値でない場合はバインドアドレスとして扱う
                    Class.forName("info.istlab.ServerTester." + className).getConstructor(String.class)
                            .newInstance(args[0]);
                }
            } else if (args.length == 2) {
                Class.forName("info.istlab.ServerTester." + className)
                        .getConstructor(int.class, String.class).newInstance(Integer.parseInt(args[0]), args[1]);
            } else {
                System.err.println("Usage: java info.istlab.ServerTester." + className + " [port] [bind-address]");
            }
        } catch (Exception e1) {
            e1.printStackTrace();
        }
    }

    public static boolean isNumeric(String str) {
        if (str == null || str.isEmpty()) {
            return false;
        }
        try {
            Integer.parseInt(str);
            return true;
        } catch (NumberFormatException e) {
            return false;
        }
    }

    public Server(int port, String bindaddress) {
        expectedPort = port;
        expectedAddress = bindaddress;
        try {
            serverSocket = new ServerSocket();
            serverSocket.bind(new InetSocketAddress(bindaddress, port));
            bindFailed = false;
        } catch (BindException bex) {
            bindFailed = true;
            JOptionPane.showMessageDialog(Host.mainhost,
                    getClass().getName() + " 起動時に、サーバソケットのバインドに失敗しました。\n\nポート " + expectedPort + " とバインドアドレス "
                            + expectedAddress + " の組み合わせは使用されています。\n既存のサービスを停止するか、ポート番号/バインドアドレスを変更してください。",
                    "エラー", JOptionPane.ERROR_MESSAGE);
        } catch (IOException e) {
            System.err.println(e);
            // System.err.println("バインド失敗。ポート番号 " + port + " (Bind-address: " + bindaddress
            // + " 向け) がすでにつかわれているようです");
            // System.err.println("ポート番号またはバインドアドレスを変更してください。");
            // System.err.println("またはコマンド killall java を実行して全てのJavaプロセスを終了してください。");
        }
        System.out.println(getClass().getName() + " [" + bindaddress + ":" + port + "] started.");
    }

    public void handleRequest() {
    }

    public void start() {
        thread = new Thread(this);
        thread.start();
    }

    public void run() {
        while (thread != null) {
            if (serverSocket.isClosed()) {
                thread = null;
            }
            if (thread != null && !serverSocket.isClosed()) {
                try {
                    handleRequest();
                } catch (Exception e) {
                    System.err.println(e);
                    thread = null;
                }
            }

        }
    }

    public String getBindAddress() {
        if (serverSocket == null) {
            return "/null";
        }
        if (serverSocket.getInetAddress() == null) {
            return "/null";
        }
        return serverSocket.getInetAddress().toString();
    }

    public int getPort() {
        return serverSocket.getLocalPort();
    }

    public boolean isClosed() {
        return serverSocket.isClosed();
    }

    public String getExpectedAddress() {
        return expectedAddress;
    }

    public int getExpectedPort() {
        return expectedPort;
    }

    public void restart() {
        try {
            serverSocket = new ServerSocket();
            serverSocket.bind(new InetSocketAddress(expectedAddress, expectedPort));
            bindFailed = false;
            start();
        } catch (BindException bex) {
            bindFailed = true;
            JOptionPane.showMessageDialog(Host.mainhost,
                    getClass().getName() + " 起動時に、サーバソケットのバインド失敗しました。\n\nポート " + expectedPort + " とバインドアドレス "
                            + expectedAddress + " の組み合わせは使用されています。\n既存のサービスを停止するか、ポート番号/バインドアドレスを変更してください。",
                    "エラー", JOptionPane.ERROR_MESSAGE);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void close() {
        try {
            serverSocket.close();
        } catch (IOException e) {
            System.err.println(e);
        }
        thread = null;
    }
}