package guang.crawler.jsonServer; import guang.crawler.localConfig.ComponentLoader; import java.io.File; import java.io.IOException; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; /** * 该类代表使用Accept机制的Socket服务器,使用JSON协议进行通信。 * * @author yang */ public class AcceptJsonServer implements Runnable, JsonServer { /** * 底层的服务器套接字 */ private final ServerSocket server; /** * 服务器使用的线程池,从而重复利用线程 */ private final ExecutorService threadPool; /** * Commandlet的加载器 */ private ComponentLoader<Commandlet> commandletLoader; /** * 服务器线程 */ private Thread serverThread; /** * 线程控制器 */ private AcceptThreadController acceptThreadController; /** * 创建一个基于Accept机制的JSON服务器,将直接选定一个未被使用的端口监听外部连接. * * @param threadNum * 需要的线程的数量 * @param configFile * 配置文件 * @param schemaFile * XSD模板文件 * @throws ServerStartException */ public AcceptJsonServer(final int threadNum, final File configFile, final File schemaFile) throws ServerStartException { this.acceptThreadController = new AcceptThreadController(); this.commandletLoader = new ComponentLoader<Commandlet>(configFile, schemaFile); try { this.commandletLoader.load(); } catch (Exception e) { throw new ServerStartException("Load config file failed!", e); } try { this.server = new ServerSocket(); } catch (IOException e) { throw new ServerStartException("Can not open socket!", e); } this.threadPool = Executors.newFixedThreadPool(threadNum); } /** * 利用指定的参数创建一个JSON服务器 * * @param port * 在指定的端口上监听. * @param backlog * 服务器套接字等待队列的大小 * @param threadNum * 线程的数量 * @param configFile * 配置文件 * @param schemaFile * XSD模板文件 * @throws ServerStartException */ public AcceptJsonServer(final int port, final int backlog, final int threadNum, final File configFile, final File schemaFile) throws ServerStartException { this.acceptThreadController = new AcceptThreadController(); this.commandletLoader = new ComponentLoader<Commandlet>(configFile, schemaFile); try { this.commandletLoader.load(); } catch (Exception e) { throw new ServerStartException("Load config file failed!", e); } try { this.server = new ServerSocket(port, backlog); } catch (IOException e) { throw new ServerStartException("Can not open socket!", e); } this.threadPool = Executors.newFixedThreadPool(threadNum); } @Override public InetAddress getAddress() { if (this.server != null) { return this.server.getInetAddress(); } return null; } @Override public int getPort() { if (this.server != null) { return this.server.getLocalPort(); } return 0; } @Override public boolean isShutdown() { if (this.acceptThreadController.getType() != AcceptThreadController.TYPE_START) { return true; } else if (this.server.isClosed() && this.threadPool.isTerminated()) { return true; } return false; } /** * 服务器的主线程 */ @Override public void run() { while (this.acceptThreadController.getType() == AcceptThreadController.TYPE_START) { Socket client; try { client = this.server.accept(); AcceptRequestHandler command = new AcceptRequestHandler(client, this.commandletLoader, this.acceptThreadController); this.threadPool.submit(command); } catch (IOException ex) { // 在accept的时候断掉了,说明是系统要求线程停止了。 break; } } // 在这里已经结束了,被要求停止 try { this.server.close(); } catch (IOException ex) { ex.printStackTrace(); } this.threadPool.shutdownNow(); } @Override public void shutdown() { this.acceptThreadController.setType(AcceptThreadController.TYPE_SHUTDOWN_NOW); try { this.server.close(); } catch (IOException e) { // Should not come here. e.printStackTrace(); } } @Override public boolean start() { if (this.serverThread == null) { this.serverThread = new Thread(this); } if ((this.serverThread != null) && !this.serverThread.isAlive()) { try { this.serverThread.start(); return true; } catch (IllegalThreadStateException e) { return false; } } return false; } @Override public void waitForStop() { if (this.serverThread.isAlive()) { try { this.serverThread.join(); this.threadPool.awaitTermination(1, TimeUnit.HOURS); } catch (InterruptedException e) { return; } } } }