zoukankan      html  css  js  c++  java
  • HTTP服务器(1)

    单文件服务器

    导语

    在研究HTTP服务器时,我们可以从一个单文件服务器开始。无论接受到什么请求,这个服务器始终发送同一个文件。下面是示例代码,绑定的端口,发送的文件名以及文件的编码从命令行读取。如果省略端口则假定为端口80,如果省略编码方式默认8080

    示例代码

    import java.io.BufferedInputStream;
    import java.io.BufferedOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.net.URLConnection;
    import java.nio.charset.Charset;
    import java.nio.file.Files;
    import java.nio.file.Path;
    import java.nio.file.Paths;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.logging.FileHandler;
    import java.util.logging.Handler;
    import java.util.logging.Logger;
    
    public class SingleHttpServer {
    	private static final Logger logger = Logger.getLogger("SingleFileHttpServer");
    	private static  Handler handler;
    	private final byte[] content;
    	private final byte[] header;
    	private final int port;
    	private final String encoding;
    	
    	public SingleHttpServer(String _content, String _encoding, String mimeType, int _port) {
    		this(_content.getBytes(), _encoding, mimeType, _port);
    	}
    	
    	public SingleHttpServer(byte[] _content, String _encoding, String mimeType, int _port) {
    		try {
    			handler = new FileHandler("SingleFileHttpServer.log");
    		} catch (Exception e) {
    			throw new RuntimeException("cannot create log file!");
    		}
    		logger.addHandler(handler);
    		content = _content;
    		encoding = _encoding;
    		String header1 = "HTTP/1.1 200 OK
    "
    				+ "Server: OneFile
    "
    				+ "Content-length: "+ content.length +"
    "
    				+ "Content-Type: " + mimeType + ";charset=" + encoding + "
    
    ";
    		header = header1.getBytes(Charset.forName("utf-8"));
    		port = _port;
    	}
    	
    	public void start() {
    		ExecutorService pool = Executors.newFixedThreadPool(100);
    		try (ServerSocket server = new ServerSocket(port)) {
    			logger.info("Accepting connections on port " + server.getLocalPort());
    			logger.info("Data to be sent:");
    			logger.info(new String(content, encoding));
    			while (true) {
    				Socket socket = server.accept();
    				pool.execute(new HttpHandler(socket));
    			}
    		} catch (IOException e) {
    			e.printStackTrace();
    		}
    	}
    	
    	private class HttpHandler implements Runnable {
    
    		private final Socket socket;
    		
    		public HttpHandler(Socket _socket) {
    			socket = _socket;
    		}
    
    		@Override
    		public void run() {
    			try (
    				OutputStream out = new BufferedOutputStream(socket.getOutputStream());
    				InputStream in = new BufferedInputStream(socket.getInputStream());
    			) {
    				StringBuilder request = new StringBuilder(80);
    				while (true) {
    					int c = in.read();
    					if (c == '
    ' || c == '
    ' || c == -1)break;
    					request.append((char)c);
    				}
    				if (request.toString().indexOf("HTTP/") != -1) {
    					out.write(header);
    				}
    				out.write(content);
    				out.flush();
    			} catch (IOException e) {
    				e.printStackTrace();
    			} finally {
    				try {
    					socket.close();
    				} catch (IOException e) {
    					e.printStackTrace();
    				}
    			}
    		}
    	}
    	
    	public static void main(String[] args) {
    		
    		//设置端口
    		int port;
    		try{
    			port = Integer.parseInt(args[2]);
    			if (port < 1 || port > 65535)
    				port = 8080;
    		} catch (RuntimeException e) {
    			//如果参数中没有端口,则会发生数组越界,所以需要捕获
    			port = 8080;
    		}
    		//设置编码方式
    		String encoding = "UTF-8";
    		if (args.length >= 2) encoding = args[1];
    		
    		try {
    			Path path = Paths.get(args[0]).toAbsolutePath();
    			byte[] data = Files.readAllBytes(path);
    			String contentType = URLConnection.getFileNameMap().getContentTypeFor(path.toString());
    			SingleHttpServer server = new SingleHttpServer(data, encoding, contentType, port);
    			server.start();
    		} catch (ArrayIndexOutOfBoundsException ex) {
    			System.out.println("Usage: java SingleHttpServer filename [encoding [port]]");
    		} catch (IOException e) {
    			logger.severe(e.getMessage());
    		}
    	}
    }
    

    main()方法中是从命令行读取参数。从第一个命令行读取提供的文件名。如果没有指定文件或者如果文件无法打开,就显示一条错误信息,程序推出。假定文件能够读取,就是用java7引入的Path和Files类将其内容读入byte数组。URLConnection类对文件的内容类型做出合理的猜测,将猜测的结果保存到contentTyep变量中。接下来读取第二个参数,如果没有则指定编码方式为UTF-8。

  • 相关阅读:
    科幻的意义---《超新星纪元》后记
    论文翻译第二弹--用python(或Markdown)对论文复制文本进行处理
    python note 001
    matlab读取txt文本
    VS中添加lib与dll
    Wake-Sleep(W-S)算法【转载】
    清华大学《C++语言程序设计进阶》线上课程笔记06---继承、派生、多态性
    清华大学《C++语言程序设计基础》线上课程笔记05---vector对象,对象的复制与移动,string类
    清华大学《C++语言程序设计基础》线上课程笔记04---指针
    Linux线程的信号量同步
  • 原文地址:https://www.cnblogs.com/xidongyu/p/6216372.html
Copyright © 2011-2022 走看看