Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angular/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
制作基本的Java文件服务器多线程_Java_Multithreading_Threadpool_Runnable_Serversocket - Fatal编程技术网

制作基本的Java文件服务器多线程

制作基本的Java文件服务器多线程,java,multithreading,threadpool,runnable,serversocket,Java,Multithreading,Threadpool,Runnable,Serversocket,我有一个服务器,它向它的客户端发送文本文件的内容 “server”包有一个“Main”(从cmd行args中获取端口号并对其进行解析)、“server”和一个“FileHandler”类,我想我已经在某种程度上获得了它们(使用线程池),以便服务器能够同时为两个客户端提供服务 现在,我正在尝试构建一个CLI,其中包含启动和停止服务器的选项。我希望实现两个线程,其中一个线程将侦听输入,另一个线程将侦听'accept()'调用 到目前为止,我的尝试是创建一个新类“Commander.java”,并在构

我有一个服务器,它向它的客户端发送文本文件的内容

“server”包有一个“Main”(从cmd行args中获取端口号并对其进行解析)、“server”和一个“FileHandler”类,我想我已经在某种程度上获得了它们(使用线程池),以便服务器能够同时为两个客户端提供服务

现在,我正在尝试构建一个CLI,其中包含启动和停止服务器的选项。我希望实现两个线程,其中一个线程将侦听输入,另一个线程将侦听'accept()'调用

到目前为止,我的尝试是创建一个新类“Commander.java”,并在构造函数中引入一个原子布尔值,然后将其存储在对象中,用作停止服务器线程的标志

我希望侦听“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()

3-添加
try/catch
以处理插座关闭(完全关闭):

B-在你的主课中:

1-让
服务器
实例成为类成员范围

Server myServer = new Server(port);
2-在开关(
案例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-要停止服务器,
案例2:

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

看看NIO和
Netty framework
。你不需要另一个类,也不需要Netty,试试这个:添加一个在大循环外运行的布尔变量,并将大循环更改为while(running){..},在循环中,从客户端读取
action
(请求中的部分数据),当action==SOME\u值时,将running=false,然后while()将结束,然后在class
Server
上执行清理。当在while循环中时,线程将被阻塞在
.accept()
上,直到收到连接(请求)。因此,更改布尔值不会停止应用程序,因为它已经在
while
中。理论上:它会将布尔值
running
更改为
false
,但这不会停止服务器,直到收到一个请求。@Yazan我说,
从客户端读取操作,这意味着它已经被接受,然后设置
running
变量,这是在下一个循环开始之前,所以它应该可以工作,我想是吧?哦,我刚刚注意到你有两个类,一个是
Main
,一个是
Server
,每个类都有一个
while()
循环,我想你只需要一个类,一个
while()
循环。线程管理是使用执行器完成的。FileHandler是在executors线程池的线程中执行的可运行文件处理程序。@pdem这并不是真正的答案。关键是调用
close()
@Kayaman我可以根据这个答案发布一个答案(带有代码片段)吗?@Yazan如果答案正确,请把自己击倒。我对我描述的东西没有任何专有权:)@Kayaman好的,我明白了。然后也许你可以删除第一句,第二句只是一个完美的“简单快速”解决方案。非常简洁的解决方案-感谢你的努力。
case 1: 
    // start server
    System.out.println("Starting server...");
    Thread th1 = new Thread(myServer);
    th1.start();
    System.out.println("Case continuity...");
    // server.startServer() ;
    break;
case 2:
    // stop server
    myServer.shutdown();
    System.out.println("Server stopped.\n");
    break;