爱玺玺

爱玺玺的生活日记本。wx:lb87626

java模拟web服务器,测试能用

package ex01.pyrmont;


import java.net.Socket;

import java.net.ServerSocket;

import java.net.InetAddress;

import java.io.InputStream;

import java.io.OutputStream;

import java.io.IOException;

import java.io.File;


public class HttpServer {


    /**

     * WEB_ROOT是HTML和其它文件存放的目录. 这里的WEB_ROOT为工作目录下的webroot目录

     */

    public static final String WEB_ROOT = System.getProperty("user.dir") + File.separator + "webroot";


    // 关闭服务命令

    private static final String SHUTDOWN_COMMAND = "/SHUTDOWN";


    public static void main(String[] args) {

        HttpServer server = new HttpServer();

        //等待连接请求

        server.await();

    }


    public void await() {

        ServerSocket serverSocket = null;

        int port = 8080;

        try {

            //服务器套接字对象

            serverSocket = new ServerSocket(port, 1, InetAddress.getByName("127.0.0.1"));

        } catch (IOException e) {

            e.printStackTrace();

            System.exit(1);

        }


        // 循环等待一个请求

        while (true) {

            Socket socket = null;

            InputStream input = null;

            OutputStream output = null;

            try {

                //等待连接,连接成功后,返回一个Socket对象

                socket = serverSocket.accept();

                input = socket.getInputStream();

                output = socket.getOutputStream();


                // 创建Request对象并解析

                Request request = new Request(input);

                request.parse();

                // 检查是否是关闭服务命令

                if (request.getUri().equals(SHUTDOWN_COMMAND)) {

                    break;

                }


                // 创建 Response 对象

                Response response = new Response(output);

                response.setRequest(request);

                response.sendStaticResource();


                // 关闭 socket 对象

                socket.close();

                

            } catch (Exception e) {

                e.printStackTrace();

                continue;

            }

        }

    }

}



package ex01.pyrmont;


import java.io.InputStream;

import java.io.IOException;


public class Request {


    private InputStream input;

    private String uri;


    public Request(InputStream input) {

        this.input = input;

    }


    //从InputStream中读取request信息,并从request中获取uri值

    public void parse() {

        StringBuffer request = new StringBuffer(2048);

        int i;

        byte[] buffer = new byte[2048];

        try {

            i = input.read(buffer);

        } catch (IOException e) {

            e.printStackTrace();

            i = -1;

        }

        for (int j = 0; j < i; j++) {

            request.append((char) buffer[j]);

        }

        System.out.print(request.toString());

        uri = parseUri(request.toString());

    }


    /**

     * 

     * requestString形式如下:

     * GET /index.html HTTP/1.1

     * Host: localhost:8080

     * Connection: keep-alive

     * Cache-Control: max-age=0

     * ...

     * 该函数目的就是为了获取/index.html字符串

     */

    private String parseUri(String requestString) {

        int index1, index2;

        index1 = requestString.indexOf(' ');

        if (index1 != -1) {

            index2 = requestString.indexOf(' ', index1 + 1);

            if (index2 > index1)

                return requestString.substring(index1 + 1, index2);

        }

        return null;

    }


    public String getUri() {

        return uri;

    }


}


package ex01.pyrmont;


import java.io.OutputStream;

import java.io.IOException;

import java.io.FileInputStream;

import java.io.File;

import java.io.PrintWriter;


/*

  HTTP Response = Status-Line

    *(( general-header | response-header | entity-header ) CRLF)

    CRLF

    [ message-body ]

    Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF

*/


public class Response {


    private static final int BUFFER_SIZE = 1024;

    Request request;

    OutputStream output;


    public Response(OutputStream output) {

        this.output = output;

    }


    public void setRequest(Request request) {

        this.request = request;

    }


    public void sendStaticResource() throws IOException {

        byte[] bytes = new byte[BUFFER_SIZE];

        FileInputStream fis = null;

        try {

            //将web文件写入到OutputStream字节流中

        //感觉有部分代码有问题,就是OutputStream 向页面输出静态文件的时候,按现在的代码浏览器无法正常展示的。我改了一下,在前面加了

        //"HTTP/1.1 200\r\n" + "Content-Type: text/html\r\n" + "Content-Length: " + file.length() + "\r\n" + "\r\n"

        //才可以

            File file = new File(HttpServer.WEB_ROOT, request.getUri());

            if (file.exists()) {

            //输出浏览器判断用的头信息

            String headStr="HTTP/1.1 200\r\n" + "Content-Type: text/html\r\n" + "Content-Length: " + file.length() + "\r\n" + "\r\n";

            PrintWriter pw=new PrintWriter(output, true);

            pw.println(headStr);

                fis = new FileInputStream(file);

                int ch = fis.read(bytes, 0, BUFFER_SIZE);

                while (ch != -1) {

                    output.write(bytes, 0, ch);

                    ch = fis.read(bytes, 0, BUFFER_SIZE);

                }

            } else {

                // file not found

                String errorMessage = "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) {

            // thrown if cannot instantiate a File object

            System.out.println(e.toString());

        } finally {

            if (fis != null)

                fis.close();

        }

    }

}


两个关键点:

1,如果是dos控制台运行,网站目录在src路径下。如果是eclipse在bin里面的目录。

2,Response必须输出浏览器需要的头信息,如果不在这里输出,就需要把头信息写在web文件里面。

//输出浏览器判断用的头信息

            String headStr="HTTP/1.1 200\r\n" + "Content-Type: text/html\r\n" + "Content-Length: " + file.length() + "\r\n" + "\r\n";

            PrintWriter pw=new PrintWriter(output, true);

            pw.println(headStr);


TIM图片20171130111131.gif

(如果路径里面有非java的源文件,如class文件则不能用这种编译,需要删除class文件后才能编译)

TIM图片20171130111444.gif

(服务器接收到浏览器发来的头信息)


源码下载:

链接:https://pan.baidu.com/s/1i5hB9rf 密码:nj9c

发表评论:

Powered By Z-BlogPHP 1.4 Deeplue Build 150101

Copyright Your WebSite.Some Rights Reserved.

蜀ICP备11021721号-5