使基本Java文件服务器具有多线程

时间:2016-03-29 07:04:48

标签: java multithreading threadpool runnable serversocket

我有一台服务器向其客户端发送文本文件的内容。

'服务器'包裹有一个' 主要' (从cmd行args获取端口号并解析它),' 服务器'和' FileHandler '我认为我已经通过某种方式获得了它们(使用线程池),因此服务器可以同时为两个客户端提供服务。

现在我正在尝试使用选项来构建一个CLI来启动&停止服务器。我希望实现2个线程,其中一个线程将监听输入,另一个线程将监听' accept()'调用

到目前为止,我尝试创建一个新课程' Commander.java '并在构造函数中接受 AtomicBoolean ,然后将其存储在对象中,以用作停止服务器线程的标志。

我想要正在收听' accept()'打电话定期检查是否已停止请求 - 如何使用我的' Commander'类?

包含一些代码段(a.k.a.到目前为止我的尝试),以便您更好地理解:

class Server implements Runnable 
{
Socket sock;
ExecutorService executor;
private int port ;

public Server(int p) {
    port = p ;
    executor = Executors.newFixedThreadPool(2);
}

public void startServer() {
ServerSocket s = new ServerSocket(port);
...
while (true)
{
    Socket temp = s.accept();
    sock = temp;
    executor.execute(new FileHandler(sock));
    // serveFile(temp) ;
}

public void run() {
    startServer();
}
}

public class Main {

public static void main(String[] args) {

    while(true) {
        System.out.println("Main menu:\n" +
                       " 1 - Start server\n"+
                       " 2 - Stop Server\n"+
                       " 0 - Exit");
        int in = Integer.parseInt(scanner.nextLine());

        switch(in) {
            case 1: 
                // start server
                System.out.println("Starting server...");
                Thread th1 = new Thread(new Server(port));
                th1.start();
                System.out.println("Case continuity...");
                // server.startServer() ;
                break;
            case 2:
                // stop server
                System.out.println("Server stopped.\n");
                break;
            case 0:
                // exit
                System.exit(0);
                break;
            }
        }
     }
 }

class FileHandler implements Runnable {

Socket socket;

public FileHandler(Socket socket) {
    this.socket = socket;
}

private void serveFile() {
 ...code for serving file...
}


public void run() {
    serveFile();
}
}

public class Commander implements Runnable
{

 private AtomicBoolean bool;

 public Commander(AtomicBoolean bool) {
    this.bool = new AtomicBoolean(bool);
 }

 public boolean value() {
    return bool.get();
 }

2 个答案:

答案 0 :(得分:2)

你的做法是错误的。在accept()上被阻止的线程不应该做任何事情,只需等待并启动新线程(或提交新任务)作为连接。

如果要关闭服务器,请在close()上调用ServerSocket(当然是从其他线程)。 accept()上被阻止的线程将抛出SocketException,然后您可以清理并退出。

答案 1 :(得分:1)

基于@Kayaman Answer

A-在您的服务器类:

1-让ServerSocket成为类成员范围:

ServerSocket s = new ServerSocket(port);

2-添加方法shutdown()

public void shutdown(){
    try{
        s.close();
    }catch(Exception e){
        e.printStacktrace();
    }
}

3-添加try/catch来处理套接字关闭(执行干净关闭):

while (true)
{
    try{
        Socket temp = s.accept();
        sock = temp;
        executor.execute(new FileHandler(sock));
        // serveFile(temp) ;
    }catch(SocketException ex){
        doAcleanShutdown();
    }
}

B-在您的主要课程中:

1- let Server实例是类成员范围

Server myServer = new Server(port);

2-在开关(case 1:)中使用myServer实例

case 1: 
    // start server
    System.out.println("Starting server...");
    Thread th1 = new Thread(myServer);
    th1.start();
    System.out.println("Case continuity...");
    // server.startServer() ;
    break;

3-停止服务器case 2:

case 2:
    // stop server
    myServer.shutdown();
    System.out.println("Server stopped.\n");
    break;