使用Java实现Web服务器编程

以下是个人学习过程中的一点记录

在进行实验完成一个简单的web服务器之前,我们要对HTTP协议报文有一个更深的了解,以下即为请求报文



在平常使用web服务器时,我们关心请求方法(一般是GET/POST),URL,以及如果是POST方法我们还关心请求包体中的数据,因此我们需要对报文进行分解处理。

下面可以简单分析一下我们具体要执行的步骤


创建ServerSocket对象,利用serverSocket对象中的accept()函数等待请求的到达,之后处理完成后重新进行等待。

创建Request对象,主要进行分词提取出我们需要的方法,URL,以及报文。

创建Response对象,主要根据request后得到的请求方法采取不同的处理方式并输出。

执行时,获取inputstream和outputstream,分别提供给Request和Response对象。



1. 首先是web服务器类

构造ServerSocket函数,将其绑定为本机的8080端口

然后进入while循环,accept()函数等待,没有时就进行阻塞

然后将输入流输出流分别交给请求和响应函数

执行完毕后,关闭ServerSocket,让其重新进入while循环


2. request类

首先创建4个变量,输入流,url,方法,数据包体


然后在构造函数中,根据 方法,url,版本之间的空格进行spilit,然后一次进行赋值


最后创建get方法即可获取值


3.response类

首先创建输出流和请求类变量,然后根据构造函数进行赋值


然后根据方法的不同,进行不同的处理

首先建立一个HashMap,存取参数


当方法为POST时,spilit拿出数据体,并存入公共域


然后模拟控制器,执行必要功能(此处为叠加计算值)


最后将结果加入一段html段中一起显示


注意要加入响应头,否则无法解析,会报错并且不会显示

当方法为GET时,根据参数的提交方式,对url进行解析,取出参数并存入公共域



4.测试用前端根据个人要求修改,适当修改后台的模拟处理即可运行。


以下贴上完整代码


public class WebServer {

    /**

     *@param args

     */

    public static void main(String[] args) {

       // TODOAuto-generated method stub


       ServerSocketserverSocket = null;

       try {

           // 使用本机

           serverSocket = newServerSocket(8080, 1, InetAddress.getByName("localhost"));

       }catch (IOException e) {

           e.printStackTrace();

       }

       while (true) {

           try {

              // 等待连接

              Socketsocket = serverSocket.accept();

              InputStreaminput = socket.getInputStream();

              OutputStreamoutput = socket.getOutputStream();

              // request解析出url

              Requestrequest = new Request(input);

              // response输出

              Responseresponse = new Response(output, request);

              response.response();

              socket.close();

           }catch (Exception e) {

              e.printStackTrace();

              continue;

           }

       }

    }

}


public class Request {


    // GET格式,类似也存在POST

    // GET /test.html HTTP/1.1

    // Host:localhost:8080

    // Connection: keep-alive

    // Upgrade-Insecure-Requests: 1

    // User-Agent:Mozilla/5.0 (Windows NT 10.0;WOW64) AppleWebKit/537.36 (KHTML,

    // likeGecko)Chrome/74.0.3729.169Safari/537.36

    // Accept:

    // text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3

    // Accept-Encoding:gzip,deflate,br

    // Accept-Language:zh-CN,zh;q=0.9,en;q=0.8


    private InputStream input = null;

    private String url = null;

    private StringBuffer body = new StringBuffer(4096);

    private String method = null;


    public Request(InputStream input) {

       this.input = input;

       try {

           // 下面分解url,首先读取内容到body中

           byte[] buffer = new byte[4096];

           int len = input.read(buffer);

           for (int i = 0; i < len; i++)

              body.append((char) buffer[i]);



           // 拿到报文要获取url,根据注释中的格式进行分析

           url = body.toString().split(" ")[1];

           method = body.toString().split(" ")[0];

       }catch (IOException e) {

           // TODO Auto-generated catch block

           e.printStackTrace();

       }

    }


    public String getUrl() {

       return url;

    }


    public String getBody() {

       return body.toString();

    }


    public String getMethod() {

       return method;

    }

}


public class Response {


    private OutputStream output;

    private Request request;

    HashMapmemory = new HashMap();


    public Response(OutputStream output, Request request) {

       this.output = output;

       this.request = request;

    }


    public void response() {


       byte[] bytes = new byte[4096];

       FileInputStreamfilestream = null;

       try {


           if (request.getMethod().equals("POST")) {


              // 拿出数据体,以KV对存储

              Stringbody = request.getBody();

              String[]bodys = body.split("\r|\n");

              String[]parms = bodys[bodys.length - 1].split("&|=");

              for (int i = 1; i < parms.length - 1; i += 2) {

                  memory.put(parms[i - 1], parms[i]);

              }


              // 此处模拟控制器

              int result = 0;

              result+= Integer.parseInt(memory.get("t1")) + Integer.parseInt(memory.get("t2"))

                     + Integer.parseInt(memory.get("t3")) + Integer.parseInt(memory.get("t4"))

                     + Integer.parseInt(memory.get("t5")) + Integer.parseInt(memory.get("t6"))

                     + Integer.parseInt(memory.get("t7")) + Integer.parseInt(memory.get("t8"))

                     + Integer.parseInt(memory.get("t9")) + Integer.parseInt(memory.get("t10"))

                     + Integer.parseInt(memory.get("t11")) + Integer.parseInt(memory.get("t12"))

                     + Integer.parseInt(memory.get("t13")) + Integer.parseInt(memory.get("t14"))

                     + Integer.parseInt(memory.get("t15"));


              Stringbuf = "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML

4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\r\n"

                     +"<html>\r\n" + "<head>\r\n"

                     +"<meta

http-equiv=\"Content-Type\" content=\"text/html;

charset=UTF-8\">\r\n"

                     +"<title>Insert title

here</title>\r\n" + "</head>\r\n" + "<body>\r\n" + "\r\n" + " 你的测试得分为"

                     +result + "</body>" + "</html>";

              StringresponseHead = "HTTP/1.1 200 ok\r\nContent-Type:

text/html\r\nContent-Length: " + buf.length()

                     +"\r\n\r\n";

              output.write(responseHead.getBytes());

              output.write(buf.getBytes());


           }else {

              String[]parms = request.getUrl().split("\\?")[1].split("&|=");

              for (int i = 0; i < parms.length - 1; i += 2) {

                  memory.put(parms[i], parms[i + 1]);

              }


              // 模拟控制器

              Filefile = new File("./src" + request.getUrl().split("\\?")[0]);

              if (file.exists()) {

                  filestream = new FileInputStream(file);

                  // 加入头

                  StringresponseHead = "HTTP/1.1 200 ok\r\nContent-Type:

text/html\r\nContent-Length: "

                         +file.length() + "\r\n\r\n";

                  output.write(responseHead.getBytes());

                  output.write((memory.get("name") + "你好").getBytes());

                  int len = 0;

                  while ((len = filestream.read(bytes, 0, 4096)) != -1) {

                     output.write(bytes, 0, len);

                  }

              }else {

                  StringerrorMessage = "HTTP/1.1 404 File Not Found\r\n" + "Content-Type: text/html\r\n"

                         +"Content-Length: 23\r\n" + "\r\n" + "<h1>File Not Found</h1>";

                  output.write(errorMessage.getBytes());

              }

           }

       }catch (Exception e) {

       }finally {

           try {

              if (filestream != null)

                  filestream.close();

           }catch (IOException e) {

              // TODO Auto-generated catch block

              e.printStackTrace();

           }

       }

    }

}

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容