首页 > 学院 > 开发设计 > 正文

一个简单的web服务器例子

2019-11-14 23:33:20
字体:
来源:转载
供稿:网友
一个简单的web服务器例子

一个简单的web容器小例子,功能十分简单,只能访问静态资源,对于新手来说还是有一定的意义。主要分三个类

1、server类:主要功能开启socketServer,阻塞server,接收socket访问,解析request,创建request,作出响应

public class TestServer1 {        PRivate boolean shutdown = false;        // web目录webroot    public static final String WEB_ROOT = System.getProperty("user.dir")             + File.separator +  "WebRoot";        public static final String SHUTDOWN_COMMAND = "/SHUTDOWN";        public static void main(String[] args) {        TestServer1 server = new TestServer1();        server.await();    }        public void await() {                // 第一步、创建出serverSocket监听本机8080端口        ServerSocket server = null;        int port = 8080;        try {            server = new ServerSocket(port, 1, InetAddress.getByName("127.0.0.1"));        } catch (Exception e) {            e.printStackTrace();        }                 // 第二步、轮询阻塞住socketServer        while(!shutdown) {            Socket socket = null;            InputStream input = null;            OutputStream output = null;                        try {                socket = server.accept();                input = socket.getInputStream();                output = socket.getOutputStream();                                // 第三步、创建出request,解析request请求                Request req = new Request(input);                req.parseRequest();                                // 第四步、创建response                Response response = new Response(output);                response.setRequest(req);                                // 第五步、发送简单静态资源,关闭socket结束本次会话                response.sendStaticRes();                socket.close();                                // 关闭指令                shutdown = req.getUri().equals(SHUTDOWN_COMMAND);            } catch (IOException e) {                e.printStackTrace();            }        }            }    }

当然了上面的是最简单的实现,也不能实现多线程,实际上的web容器肯定会创建一个线程池来接收请求

2、request 主要的工作解析input流,封装成request

class Request {        private InputStream input;        private String uri;        public Request(InputStream input) {        this.input = input;    }            /**     * 解析request请求内容     * GET /index.html HTTP/1.1     *    Accept: text/html, application/xhtml+xml, *//*     *    Accept-Language: zh-CN     *    User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; MALCJS; rv:11.0) like Gecko     *    Accept-Encoding: gzip, deflate     *    Host: localhost:8080     *    DNT: 1     *    Connection: Keep-Alive     *    Cookie: 这个地方应该如果有cookie,如果有session还有jsessionId的     */    public void parseRequest() {     // 为什么只获取2048个字符,这是因为request请求内容的长度,出于安全或者其他方面的考虑,在浏览器端和服务器端都会做这么一个限制。         StringBuffer buffer = new StringBuffer(2048);        byte[] bytes = new byte[2048];        int i;        try {            i = input.read(bytes);        } catch (IOException e) {            e.printStackTrace();            i=-1;        }        for(int k=0; k<i; k++) {            buffer.append((char)bytes[k]);        }        System.out.println(buffer.toString());        uri = parseUri(buffer.toString());    }        /**     * GET /index.html HTTP/1.1 uri的位置     * @param reqStr     * @return     */    private String parseUri(String reqStr) {        int index1, index2;        index1 = reqStr.indexOf(' ');        if (index1 != -1) {          index2 = reqStr.indexOf(' ', index1 + 1);          if (index2 > index1)            return reqStr.substring(index1 + 1, index2);        }        return null;    }        public String getUri() {        return uri;    }    }

解析成的http请求的具体内容,作为web开发人员应该要熟悉每个字段的意义,这个请求是浏览器本身按照http协议封装的一个请求,能够手写出这个请求当然更好。

3、response 通过request的uri找到对应的资源对请求作出响应,实际的情况肯定是有静态和动态资源例如servlet/filter等等,但是这里只是做了简单的静态的处理了

class Response {        private OutputStream output;        private Request request;        public Response(OutputStream output) {        this.output = output;    }        public void setRequest(Request req) {        this.request = req;    }        /**     * 简单处理静态资源     * @throws IOException     */    public void sendStaticRes() throws IOException {                FileInputStream fis = null;        try {            File staticFile = new File(TestServer1.WEB_ROOT, request.getUri());            if(staticFile.exists()) {                fis = new FileInputStream(staticFile);                int i = 0;                byte[] buf = new byte[1024];          // 流的对拷                i = fis.read(buf, 0, 1024);                while(i!=-1) {                    output.write(buf, 0, i);                    i = fis.read(buf, 0, 1024);                }            } else {                // file not found 404                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) {            e.printStackTrace();        } finally{            if(fis!=null)                fis.close();            fis = null;        }    }}

同样响应内容你也应该要熟悉哪些组成部分

HTTP/1.1 200 OK  //响应行Date: Sat, 31 Dec 2005 23:59:59 GMTContent-Type: text/html;charset=ISO-8859-1Content-Length: 122<html><head><title>Test</title></head><body>This my page</body></html>

至此一个简单的web容器就写好了,能够访问webRoot目录下的静态资源。

可以通过浏览器访问,也可以通过telnet端进行访问。在cmd命令行下telnet localhost 8080,就会连接上socketServer,然后就会等待输入,自然我们输入对应的请求报文,回车响应内容就出现了。

以上原创文章出自老罗家的树博客地址:http://www.VEVb.com/TimBing/


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表