2

因此,我正在用 Java 制作一个聊天服务器,以摆脱对 Hamachi 在我的 Minecraft 服务器中托管和通信的依赖。它完美地工作,除了一件事:我无法弄清楚如何服务器添加命令。我的主循环如下:

/*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

我认为您的命令处理器应该在另一个线程中。恕我直言,服务器应该始终有一个线程,唯一的工作就是接收新连接并分派它。处理您的输入应该是其他线程的一部分。

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 回答