Web服务器原理

目录

  • 实现一个web服务器
  • 代码实现
  • 测试方法:
  • 运行结果:
  • 出现的问题:
  • 扩展——网络编程:
  • 由该程序理解Web服务器的工作原理

实现一个web服务器

服务器监听一个端口,并读取浏览器的请求信息,从该信息提取出访问的资源(这里为文件名)。并在工作目录下查找是否有该资源,有则输出资源内容,否则返回404

代码实现

代码为自己手动输入,并加入注释帮助理解

package webserver;

import java.io.*;
import java.net.*;

public class WebServer {

    /**
     * web服务器:实现200和404操作
     * 原理:
     * 服务器监听一个端口,并读取浏览器的请求信息,从该信息提取出访问的资源(这里为文件名)。并在工作目录下查找是否有该资源,有则输出资源内容,否则返回404
     * 测试方法:
     * 1、用String path=System.getProperty("user.dir");获取当前的工作目录,并在该目录下放要测试的文件
     * 2、访问127.0.0.1:8080/HelloWorld.html
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        ServerSocket server = null;
        Socket s=null;
        try
        {
            //参数:(int port, int backlog, InetAddress bindAddr)
            server=new ServerSocket(99,3,InetAddress.getByName("127.0.0.1"));
        }catch(Exception e)
        {
            e.printStackTrace();
        }
        while(true)
        {
            try{
                /*
                 * Listens for a connection to be made to this socket and accepts it. 
                 */
                s=server.accept();
                OutputStream output=s.getOutputStream();
                InputStream input=s.getInputStream();
                
                //通过自实现reques类获取请求参数
                Request request=new Request(input);
                String filename=request.getUri();
                
                //通过自实现response类处理,传入请求资源名,并响应请求信息
                Response response=new Response(output,filename);
                response.response();

            }catch(Exception e)
            {
                e.printStackTrace();
            }
        }
    }

}
package webserver;

import java.io.*;

/*
 * 获取请求的信息,并返回资源
 * 返回请求资源文件名
 */
public class Request {
    
    InputStream input;
    
    public Request(InputStream input){
        this.input = input;
    }
    
    /*
     * 自写的获取资源URI的方法
     */
    public String getUri(){
        String content = null;
        //String str = null;
        
        //对需要频繁处理的字符串, 使用StringBuffer类操作
        StringBuffer request = new StringBuffer();
        //作用?将输入流中的存入字节数组,在存入SB
        byte[] buffer = new byte[2048];
        int i = 0;
        
        try{
            i = input.read(buffer);
        }catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
            i = -1;
        }
        
        for(int k = 0; k < i; ++k){
            request.append((char)buffer[k]);
        }
        
        content = request.toString();
        
        /*    
         *以下方法错误!用该返回会使浏览器不断处于请求连接状态
         *  BufferedReader br=new BufferedReader(new InputStreamReader(input));
            while((str=br.readLine())!=null)
            {
                content=content+str+"\r\n";
            }
         */ 
        
        if(content != null){
            return getFileName(content);
        }else{
            return null;
        }
    }
    
    /*
     * 关键:字符串(即文件名(即资源路径))格式
     */
    public String getFileName(String content){
        int a, b;
        a = content.indexOf(' ');   //文件名的格式???
        
        if(a != -1){
            /*
             * Returns the index within this string of the first occurrence of the specified character, 
             * starting the search at the specified index. 
             */
            b = content.indexOf('?', a+1);
            if(b == -1){
                b = content.indexOf(' ', a+1);
            }
            
            /*
             * a+2:beginIndex; b:endIndex
             */
            return content.substring(a+2, b);
        }
        return null;
    }
}
package webserver;

import java.io.*;

/*
 * 响应并处理请求信息
 */

public class Response {
    public OutputStream output;
    public String fileName;
    
    //static final定义常量,不可更改
    private static final int BUFFER_SIZE = 1024;
    
    public Response(OutputStream output, String fileName){
        this.output = output;
        this.fileName = fileName;
    }
    
    public void response() throws IOException{
        //"user.dir" 是固定的工作目录???
        String path = System.getProperty("user.dir");
        byte[] buffer = new byte[BUFFER_SIZE];
        
        int ch;
        FileInputStream fis = null;
        
        if(path != null &&fileName != null){
            /*
             * 内置方法:Creates a new File instance from a parent pathname string and a child pathname string. 
             * request获得用户请求文件名,结合文件目录,生成File类
             */
            File file = new File(path, fileName);
            System.out.println(path + " " + fileName);
            String str = "";
            
            /*
             * 模拟web服务器响应,生成响应头等信息,并返回html文件
             */
            /*
             * 如果文件存在,则返回请求结果,打印请求信息
             */
            if(file.exists()){
                System.out.println("find");
                //FileInputStream读取文件内容,并使用OutputStream输出
                fis = new FileInputStream(file);
                str = "HTTP/1.1 200 OK \r\n" +
                "Content-Type: text/html\r\n" + 
                "\r\n";
                output.write(str.getBytes());
                
                //循环读取,存入缓冲字节数组,并输出
                ch = fis.read(buffer);
                while(ch != -1){
                    output.write(buffer, 0 , ch);
                    ch = fis.read(buffer, 0, BUFFER_SIZE);
                }
            }else{
                /*
                 * 如果文件不存在——没有找到请求资源,响应头状态返回404信息
                 */
                System.out.println("not find");
                str = "HTTP/1.1 404 File Not Found \r\n" +
                 "Content-Type: text/html\r\n" + 
                 "Content-Length: 100\r\n" + 
                 "/r/n" + 
                 "

404 File Not Found!

"; output.write(str.getBytes()); } } output.close(); } }

测试方法:

  1. 在目录下存入指定资源html文件以便访问,HTML文件实现如下


    
        hello world
    
    
        

hello world!

  1. 通过打印达到user.dir为 “D:\工作环境\SimpleServer”
    不用新建一个user.dir文件夹,直接把html文件放在同一个目录下
    Web服务器原理_第1张图片

  2. 运行应用,在浏览器中输入

运行结果:

  1. 输入正确资源名
    Web服务器原理_第2张图片
    Web服务器原理_第3张图片
    2.输入不正确资源名
  • 在谷歌浏览器下,输入不存在资源名会一直加载而没有显示404(为什么??)
    1091489-20190315083222082-1734271640.png
  • 在IE浏览器下成功显示404
    Web服务器原理_第4张图片

出现的问题:

  1. 多次操作会在套接字连接时出现空指针异常,了解到是端口占用问题

Web服务器原理_第5张图片

  • 解决方法:
    1. 关闭端口占用:
      在命令行中输入netstat -ano 找到被占用端口号

    Web服务器原理_第6张图片

    Web服务器原理_第7张图片
    打开任务管理器,找到端口号对应进程ID对应的进程,点击结束进程即可解决占用
    Web服务器原理_第8张图片

    1. 更换new ServerSocket(99,3,InetAddress.getByName("127.0.0.1"));里的端口号
  1. 始终404错误!:打印可知搜索路径为,D:\工作环境\SimpleServer
    • 所以解决方案为,将html资源文件放在“ D:\工作环境\SimpleServer”该目录下(我之前同java文件放在src目录下)
      Web服务器原理_第9张图片

扩展——网络编程:

  • Socket编程步骤
    服务器端创建ServerSocket对象,调用accept方法返回Socket对象
    客户端创建Socket对象,通过端口连接到服务器
    客户端、服务器端都使用Socket中的getInputStream方法和getOutputStream方法获得输入流和输出流,进一步进行数据读写操作

(InetAddress用来描述主机地址;
Socket用来创建两台主机之间的连接;
ServerSocket用来侦听来自客户端的请求;
Socket通常称作“套接字”,通常通过“套接字”向网络发出请求或者应答网络请求。)

由该程序理解Web服务器的工作原理

  • 一组我认为很好理解的源于网络的工作原理图解
    参考web服务器工作原理

Web服务器原理_第10张图片
Web服务器原理_第11张图片
Web服务器原理_第12张图片

转载于:https://www.cnblogs.com/chacha-z/p/10534897.html

你可能感兴趣的:(Web服务器原理)