import java.io.*;
import java.net.*;
import java.util.concurrent.*;
public class FileServer {
private int port = 8000;
private int portForShutdown = 8001; // 用于监听关闭服务器命令的端口
private final int POOL_SIZE = 4; // 单个CPU时线程池中工作线程的数目
private String fileFolderPath;//文件保存的顶级目录
private ServerSocket serverSocket;
private ServerSocket serverSocketForShutdown;
private ExecutorService executorService; // 线程池
private boolean isShutdown = false; // 服务器是否已经关闭
private Thread shutdownThread = new Thread() { // 负责关闭服务器的线程
public void start() {
this.setDaemon(true); // 设置为守护线程(也称为后台线程)
super.start();
}
public void run() {
while (!isShutdown) {
Socket socketForShutdown = null;
try {
socketForShutdown = serverSocketForShutdown.accept();
BufferedReader br = new BufferedReader(new InputStreamReader(socketForShutdown.getInputStream()));
String command = br.readLine();
if (command.equals("shutdown")) {
long beginTime = System.currentTimeMillis();
socketForShutdown.getOutputStream().write("the server is shutting down...\r\n".getBytes());
isShutdown = true;
// 请求关闭线程池
// 线程池不再接收新的任务,但是会继续执行完工作队列中现有的任务
executorService.shutdown();
// 等待关闭线程池,每次等待的超时时间为30秒
while (!executorService.isTerminated())
executorService.awaitTermination(30,TimeUnit.SECONDS);
serverSocket.close(); // 关闭与EchoClient客户通信的ServerSocket
long endTime = System.currentTimeMillis();
socketForShutdown.getOutputStream().write(("the server has already shut down!!!," + "it cost "+ (endTime - beginTime) + " millisecond\r\n").getBytes());
socketForShutdown.close();
serverSocketForShutdown.close();
} else {
socketForShutdown.getOutputStream().write(
"wrong commond\r\n".getBytes());
socketForShutdown.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
};
public FileServer(String fileFolderPath) throws IOException {
this.fileFolderPath=fileFolderPath;
initFileFolderPath(this.fileFolderPath);
serverSocket = new ServerSocket(port);
//serverSocket.setSoTimeout(60000); // 设定等待客户连接的超过时间为60秒
serverSocketForShutdown = new ServerSocket(portForShutdown);
// 创建线程池
executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()* POOL_SIZE);
shutdownThread.start(); // 启动负责关闭服务器的线程
System.out.println("the server has started");
System.out.println("waiting for clients' connection...");
}
public void service() {
while (!isShutdown) {
Socket socket = null;
try {
socket = serverSocket.accept();
//socket.setSoTimeout(60000); // 把等待客户发送数据的超时时间设为60秒
executorService.execute(new Handler(socket,this.fileFolderPath));
} catch (SocketTimeoutException e) {
// 不必处理等待客户连接时出现的超时异常
} catch (RejectedExecutionException e) {
try {
if (socket != null)
socket.close();
} catch (IOException x) {
}
return;
} catch (SocketException e) {
// 如果是由于在执行serverSocket.accept()方法时,
// ServerSocket被ShutdownThread线程关闭而导致的异常,就退出service()方法
if (e.getMessage().indexOf("socket closed") != -1)
return;
} catch (IOException e) {
e.printStackTrace();
}
}
}
/*
* 初始化文件目录:如果输入目录不存在则生成目录 如果输入目录为文件则退出系统
*/
private void initFileFolderPath(String fileFolderPath) throws IOException{
File fileFolder=new File(fileFolderPath);
if(fileFolder.isFile()){
System.out.println("the folder is not exist!");
System.exit(0);
}
if(!fileFolder.exists()){
fileFolder.createNewFile();
System.out.println("create folder success!");
}
}
public static void main(String args[]) throws IOException {
new FileServer(args[0]).service();
}
}