2

そこで、Javaでチャットサーバーを作成して、Minecraftサーバーでのホスティングと通信をHamachiに依存しないようにしています。サーバーにコマンドを追加する方法がわからないということを除けば、完全に機能します。私のメインループは次のようになります。

/*Executed in constructor*/
public void listen(int port) throws IOException {
    //Initialize the ServerSocket
    ss = new ServerSocket(port);
    System.out.println("Listening on " + InetAddress.getLocalHost() + ":" + ss.getLocalPort());

    running = true;

    //Keep accepting connections
    while (running) {
        //Get the incoming connection
        Socket s = ss.accept();
        System.out.println("Connection from: " + getFullIP(s));

        //Create a DataOutputStream for writing data to the other side
        DataOutputStream dataOut = new DataOutputStream(s.getOutputStream());

        //Save this stream so I don't have to make it again
        outputStreams.put(s, dataOut);

        //Create a new thread for this connection
        new ServerThread(this, s);

        if (!running) {
            stop();
        }
        Scanner cmdScanner = new Scanner(System.in);
        String command = cmdScanner.next();
        processCommand(command);
    }
}

このコードの結果は、クライアントがサーバーに接続するまでコマンドを入力できないことです(のためss.accept())。コマンドを実行するまで、クライアントは接続できません(cmdScanner.next())。これを回避するにはどうすればよいですか?

4

2 に答える 2

1

コマンドプロセッサは別のスレッドにあるべきだと思います。IMHOサーバーには常に、新しい接続を受信して​​ディスパッチするだけのジョブを持つスレッドが必要です。入力の処理は、他のスレッドの一部である必要があります。

public class TestThread
{
    public static void main(String[] args)
    {
        new ConnectionDispatcher(8080).start();
        new CommandProcessor().start();
    }
}
class ConnectionDispatcher extends Thread{
    private int port;
    private OutputStream outputStreams;

    ConnectionDispatcher(int port)
    {
        this.port = port;
    }

    @Override
    public void run()
    {
        try
        {
            listen(port);
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
    }

    public void listen(int port) throws IOException
    {
        //Initialize the ServerSocket
        ss = new ServerSocket(port);
        System.out.println("Listening on " + InetAddress.getLocalHost() + ":" + ss.getLocalPort());

        boolean running = true;

        //Keep accepting connections
        while (running) {
            //Get the incoming connection
            Socket s = ss.accept();
            System.out.println("Connection from: " + getFullIP(s));

            //Create a DataOutputStream for writing data to the other side
            DataOutputStream dataOut = new DataOutputStream(s.getOutputStream());

            //Save this stream so I don't have to make it again
            outputStreams.put(s, dataOut);

            //Create a new thread for this connection
            new ServerThread(this, s);

        }
    }
}

class CommandProcessor extends Thread{
    @Override
    public void run()
    {
        Scanner cmdScanner = new Scanner(System.in);
        String command = cmdScanner.next();
        processCommand(command);
    }
}
于 2012-06-03T23:28:42.423 に答える
1

私がネットワーキングを始めたとき、私はこれと同じ問題を抱えていました。スレッドはss.accept()で停止していて、コード内で続行していません。ServerSocket専用の別のスレッドを実装する必要があります。次に例を示します。

public class Server implements Runnable
{
    ServerSocket server; // the serverSock your clients will connect to
    Thread thread; // the thread for your server
    boolean running; // whether or not the server is running

    public Server(int port)
    {
        running = false; // server is not yet running
        connect(port); // setup server
    }

    public void connect(int port)
    {
        try
        { 
            server = new ServerSocket(port); setup server on port 

            running = true; // server is running
            thread = new Thread(this); // initialize server thread
            thread.start(); // start thread
        } catch(Exception e){e.printStackTrace(); running = false;} // port is in use
    }

    public void disconnect()
    {
        try
        {
            server.close();
        }catch(Exception e){e.printStackTrace();}

        running = false;
        thread = null;
        server = null;
    }

    public void run()
    {
        while(running)
        {
            Socket client = server.accept(); // client connects to server
            // handle the client...
            ClientHandler handler = new ClientHandler(client);
        }
    }

    public class ClientHandler implements Runnable
    {
        Thread clientThread;
        DataOutputStream out;

        public ClientHandler(Socket socket)
        {
            out = new DataOutputStream(socket.getOutputStream());//setup the output stream
            clientThread = new Thread(this); // setup the new thread
            clientThread.start();   // start the thread
        }

        public void run()
        {
            /* this is where you get your input from the console and then
             * send the output to the client
             */
        }
    }
}

これにより、メインスレッドがserver.accept()でスタックするのを防ぐことができます。これがお役に立てば幸いです。

于 2012-06-03T23:41:54.027 に答える