最简单的http服务器试水"/>
最简单的http服务器试水
最简单的http服务器试水
添加了多线程的部分,处理无效请求的部分。
package com.myhttpserver;import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.ServerSocket;
import java.Socket;
import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;/*** 简易版Http服务器*/public class HttpServer {private static class MyRuntimeException extends RuntimeException{// 在这里实现它的构造方法, override methodpublic MyRuntimeException() {super();}public MyRuntimeException(String message) {super(message);}public MyRuntimeException(String message, Throwable cause) {super(message, cause);}public MyRuntimeException(Throwable cause) {super(cause);}protected MyRuntimeException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {super(message, cause, enableSuppression, writableStackTrace);}}// 创建HttpServer,先来一个构造方法,构造方法里传一个port进来/*** 构造方法* @param port 监听的端口*/public HttpServer(int port) throws IOException, InterruptedException {if(port < 1 || port > 65535){// 端口是 1 - 65535,如果不是,抛出一个自定义的异常throw new MyRuntimeException("端口错误,端口必须在1到65535之间");}// 如果是好的,服务器端要监听一个端口,就是传入的port端口,提供tcp服务。/*** Java中能接收其他通信实体连接请求的类是 ServerSocket,ServerSocket监听来自* 客户端的Socket连接,如果没有连接,它将一直处于等待状态* ServerSocket包含一个监听来自客户端连接请求的方法。* Socket accpet(): 如果接收到一个客户端Socket的连接请求,该方法将返回一个与* 客户端对应的Socket。如果没有客户端连接上来,该方法将一直处于等待状态,线程也被阻塞。*/ServerSocket serverSocket = new ServerSocket(port);// 构造具有 50 个线程的线程池ExecutorService pool = Executors.newFixedThreadPool(50);System.out.println("Http服务器已经启动了,开始监听端口:" + port);// 这里需要抛出 IO Exception// 监听了端口之后,需要接收客户端上来的请求while(true){Socket clientSocket = serverSocket.accept();// 接收了客户端的请求System.out.println("接收到来自于客户端的请求");//因为存在浏览器多次请求的问题,我们先来判断一下接收到的客户端Socket是否可用if(clientSocket != null && !clientSocket.isClosed()){// 会产生什么样的问题? 假设我们有 10 个用户来访问,某一个特别耗时// 一种思路/*** 我们在实际开发中,应该使用的都是线程池,我们不能够自己去创建线程* 因为我们创建一个线程,实际上是向操作系统的底层去申请资源,* 非常耗时。* 线程池如何来用?* 线程池构建好之后,怎么来提交我们的任务? 提交任务只能用 runnable的方式*/// (new Thread() {
// @Override
// public void run() {
// try {
// acceptToClient(clientSocket);
// // 来一个 run 方法,run方法里调用它
// } catch (IOException e){
// e.printStackTrace();
// }catch (InterruptedException e){
// e.printStackTrace();
// }
// }
// }).start();// 构建好 RunnableRunnable r = () -> {try{acceptToClient(clientSocket);} catch(IOException e){e.printStackTrace();} catch (InterruptedException e){e.printStackTrace();}};pool.submit(r);// 提交之后,从线程池里拿一个线程来运行这个任务}}}/*** 响应数据给客户端的具体方法* 一个线程来处理请求,如果我们处理具体的业务逻辑比较耗时,那么如果有下一个人* 也在请求我们的网页,就会等待。* 因为 acceptToClient(clientSocket) 没有执行完,所以 Socket clientSocket =* serverSocket.accept() 上一个还没运行完,则无法接收到下一次的请求。* 用多线程来解决问题* @param clientSocket* @throws IOException*/private void acceptToClient(Socket clientSocket) throws IOException, InterruptedException{// System.out.println("我收到了客户端请求");// 可以试着获取输入流有多少个字节InputStream clientIn = clientSocket.getInputStream();OutputStream clientOut = clientSocket.getOutputStream();/*** 去掉了 Thread.sleep,只打开一个localhost:12345,显示* 打印了三个"我收到了客户端请求"* 打印输入请求的长度,处理无效请求*/if(clientIn.available() == 0){clientOut.write("HTTP/1.1 200 ok\r\n".getBytes());clientOut.write("Server: myServer/1.0\r\n".getBytes());clientOut.write(("Date: " + (new Date()).toString() + "\r\n").getBytes());clientOut.write("Content-Type: text/html; charset = UTF-8\r\n".getBytes());// 自己的响应格式的响应头部// 响应 html 内容,先返回一个非常简单的htmlclientOut.write("\r\n".getBytes());clientOut.write("<h1>OK!</h1>".getBytes());// 响应完之后,输出流要关闭// 先强制性的把内容刷给客户端clientOut.flush();clientOut.close();return;}//Thread.sleep(10000);// 有一个特别耗时,睡了 10 s// 假设要获取test1.html(输出内容)到客户端的输出流// 输出流就是 clientOut// 把第一行的内容输出出去System.out.println("我收到了客户端请求,浏览器发送上来的请求的数据长度是: " + clientIn.available());clientOut.write("HTTP/1.1 200 ok\r\n".getBytes());clientOut.write("Server: myServer/1.0\r\n".getBytes());clientOut.write(("Date: " + (new Date()).toString() + "\r\n").getBytes());clientOut.write("Content-Type: text/html; charset = UTF-8\r\n".getBytes());// 自己的响应格式的响应头部// 响应 html 内容,先返回一个非常简单的htmlclientOut.write("\r\n".getBytes());clientOut.write("<h1>piao piao first page</h1>".getBytes());// 响应完之后,输出流要关闭// 先强制性的把内容刷给客户端clientOut.flush();clientOut.close();}public static void main(String[] args) throws IOException,InterruptedException{// 我们的服务器启动之后,需要监听一个端口new HttpServer(12345);}
}
更多推荐
最简单的http服务器试水
发布评论