簡體   English   中英

使基本Java文件服務器具有多線程

[英]Making a basic Java file server multi-threaded

我有一台服務器向其客戶端發送文本文件的內容。

'server'包有一個' Main '(從cmd行args接收端口號並解析它),' Server '和' FileHandler '類,我想我已經在某種程度上得到它們(使用線程池)這樣服務器就能同時服務於兩個客戶端。

現在我正在嘗試構建一個CLI,其中包含啟動和停止服務器的選項。 我正在尋找實現2個線程,其中一個線程將監聽輸入,另一個線程將監聽'accept()'調用。

到目前為止,我嘗試創建一個新類' Commander.java '並在構造函數中接受一個AtomicBoolean ,然后將其存儲在對象中,以用作停止服務器線程的標志。

我希望正在收聽'accept()'調用的線程定期檢查是否已經停止了請求 - 我怎樣才能在我的'Commander'類中執行此操作?

包括一些代碼片段(也就是我到目前為止的嘗試),以便您更好地理解:

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();
 }

你的方法是錯的。 accept()上被阻塞的線程不應該做什么,而是在建立連接時等待並啟動新線程(或提交新任務)。

當您想要關閉服務器時,請在ServerSocket上調用close() (當然是從不同的線程)。 accept()上阻塞的線程將拋出SocketException ,然后您可以清理並退出。

基於@Kayaman 答案

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-讓Server實例成為類成員范圍

Server myServer = new Server(port);

2-在交換機( case 1: myServer使用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;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM