01 Web原理(学习笔记,有错望指教)

一、Web简介

1、什么是Web

  • Web是一种分布式应用架构

    • 什么是分布式
      • 大型的软件系统划分成n个子系统,每个子系统独立部署及运行不同的主机,它们之间是可以相互调用及通讯
  • 基于客户端/服务端通讯(b/s),这里的客户端就是指浏览器(brower)了

    • b:浏览器
    • s:服务端
  • 基于浏览器访问

  • 基于http协议进行数据通讯

    • 客户端与服务端之间的数据通讯

2、Web的作用

  • 目的分享数据、分享信息

  • 数据存储到服务器,通过浏览器访问,获取数据

    • 数据
      • 本文内容
      • 图片
      • 视频
      • 音频

二、Web结构

  • 描述WEB原理操作的整个过程
    在这里插入图片描述

  • 具体操作细节

    • 打开浏览器输入url地址

      • url地址的格式
        • 协议名://WEB服务器的主机IP:端口/web应用名/访问资源路径
    • 浏览器会自动将url地址封装成http协议的请求部分

    • 浏览器将http协议的请求部分以流的形式发送给WEB服务器

    • WEB服务器的WEB容器就会解释http协议的请求部分,获知客户端需要访问那些资源

    • 将访问资源封装到http协议的响应正文部分,以流的形式发回给到客户端(浏览器)

    • 浏览器就会解释http协议的响应内容,获取响应正文数据,解释html文档,显示到浏览器

  • WEB结构包括

    • 客户端

      • 浏览器
      • 作用
        • 生成http协议的请求部分
    • WEB容器

      • 服务器
      • 作用
        • 解释http协议的请求内容
        • 将资源封装到http协议的响应部分,写回给客户端
    • http协议

    • url地址

三、http协议

1、简介

  • 超文本传输协议,如何在网络传输html文档数据,就是通过此协议实现

2、特点

  • 它是基于tcp/ip协议之上的应用层的协议
  • 它是请求及响应的一次过程
  • 它是无状态协议
    • http协议具有健忘症
      • 下一次请求,就会将上一次请求的数据全丢。

3、协议组成部分

在这里插入图片描述
(图中两个空行理解成两个换行)

a、Http协议的请求部分

  • 请求的提交方式(get还是post)、URI和HTTP协议的版本
POST /hello.jsp  HTTP/1.1

	“POST”为请求方式。
	“/hello.jsp”为URI。
	“HTTP/1.1”为HTTP协议版本。
  • 请求头(Request Header)
      - 以key:value形式描述

请求正文(Request Content)

  • 以post方式提交参数,此参数的数据内容写到请求正文

四、编写一个WEB服务器

1、WEB服务端

下面的代码可以看成是一个小tomcat,看不懂直接跳过,不影响后面的学习,可以先看后面的内容,看懂后面的内容后再回来看下面的代码,可以更好的理解tomcat

代码是基于IO流的,会用到IO流的知识

package server;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

/*
* 1、此类解析http协议请求部分
* 2、通过解释http协议,获知客户端提取什么资源
* 3、针对客户端作出响应
* */
public class HttpServer {
    public static void main(String[] args) {
        int port;
        ServerSocket serverSocket;
        
        try {
            port = Integer.parseInt(args[0]);
        }catch (Exception e) {
            port = 8080; //tomcat默认端口为8080
        }

        try {
            serverSocket = new ServerSocket(port);
            System.out.println("服务器正在监听端口:" + serverSocket.getLocalPort());
            
            while (true)//连续监听客户端
            {
                Socket socket=serverSocket.accept();
                service(socket);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void service(Socket socket)throws Exception
    {
        //获取输入流
        InputStream socketIn=socket.getInputStream();
        
        //睡眠500毫秒,使得客户端的数据发送完全,以防有时发送不完,在获取输入数据大小时报错
        //得有这种思想
        Thread.sleep(500); 


        //获取输入数据的大小
        int size=socketIn.available();
        
        //定义一个字节数组,数组长度即输入数据(请求)的大小
        byte buffer[]=new byte[size];
        socketIn.read(buffer);
        //将字节数组转换成字符串
        String request=new String(buffer);

        /*解析HTTP请求*/
        //获得HTTP请求的第一行
        //  \r\n表示回车换行,换行了说明第一行结束
        int endIndex=request.indexOf("\r\n");
        
        //当没有遇到\r\n时,indexOf返回的值是-1,当遇到时就返回当前索引值
        //所以当没有遇到时(即返回-1),说明输入的数据(请求)没有换行,endIndex的值就等于请求的长度
        //遇到了endIndex就等于换行的索引值
        if(endIndex==-1){
            endIndex=request.length();}

        else
        //str.substring(int beginIndex,int endIndex);截取str中从beginIndex开始
//至endIndex结束时的字符串,
        	{String firstLineOfRequest= request.substring(0,endIndex);}
//由此就得到第一行数据的内容
        System.out.println("http请求协议的第一行数据="+firstLineOfRequest);

        //解析HTTP请求的第一行
        //将请求的提交方式,uri,http版本这三个按空格分开存到数组,
        String[] parts=firstLineOfRequest.split(" ");

        String uri="";
        if(parts.length>=2)
            uri=parts[1]; //获得HTTP请求中的uri
        System.out.println("uri="+uri);
       

        //将数据封装http协议的响应内容
        /*
            1、响应第一行
                响应状态码、版本  HTTP/1.1  200  OK
            2、响应头部信息

            3、响应正文
         */

        /*创建HTTP响应结果 */
        //HTTP响应的第一行
        String responseFirstLine="HTTP/1.1 200 OK\r\n";

        //HTTP响应头
        /*决定HTTP响应正文的类型,此处作了简化处理*/
        String contentType;
        if(uri.indexOf("html")!=-1 || uri.indexOf("htm")!=-1)
            contentType="text/html";
        else if(uri.indexOf("jpg")!=-1 || uri.indexOf("jpeg")!=-1)
            contentType="image/jpeg";
        else if(uri.indexOf("gif")!=-1)
            contentType="image/gif";
        else
            contentType="application/octet-stream";  //字节流类型

        String responseHeader="Content-Type:"+contentType+"\r\n\r\n";

        //将uri指明的资源,以输入流的形式读取
        //获得读取响应正文数据的输入流
        InputStream in=HttpServer.class.getResourceAsStream("root/"+uri);

        //将数据写到客户端
        OutputStream outputStream=socket.getOutputStream();
        //写出http协议的响应第一行内容
        outputStream.write(responseFirstLine.getBytes());
        //写出http协议的响应头部信息
        outputStream.write(responseHeader.getBytes());

        //根据uri读取到的数据内容写到响应正文
        //定义一个读取响应内容的buf
        byte b[]=new byte[128];
        int len=-1;

        while ((len=in.read(b))!=-1)
        {
            outputStream.write(b,0,len);

        }

        Thread.sleep(1000);  //睡眠1秒,等待客户接收HTTP响应结果
        socket.close(); //关闭TCP连接
    }
}

五、编写一个支持动态资源Web服务器

1、什么动态资源

  • 根据请求参数,响应内容动态修改
  • (下面的代码可以看成是一个小tomcat,看不懂直接跳过,不影响后面的学习,可以先看后面的内容,看懂后面的内容后再回来看下面的代码,可以更好的理解tomcat)

2、如何实现动态资源

  • 编写一个类,此类根据用户提交的参数,作出不同的响应

  • 编写一个Servlet类

    • 编写一个接口
package server;

import java.io.OutputStream;

public interface Servlet {

    //初始化Servlet类
    public void init() throws Exception;
    //接受用户请求,作出不同的响应
    public void service(byte[] requestBuffer, OutputStream out)throws Exception;
}

  • 编写实现类
package server;

import java.io.OutputStream;

public class MyServlet implements Servlet {

    @Override
    public void init() throws Exception {

    }

    @Override
    public void service(byte[] requestBuffer, OutputStream out) throws Exception {


        /*获得请求参数username */
        String username=null;

        String request=new String(requestBuffer);

        //获得HTTP请求的第一行
        String firstLineOfRequest=
                request.substring(0,request.indexOf("\r\n"));
        //解析HTTP请求的第一行
        将请求的提交方式,uri,http版本这三个按空格分开存到数组part
        String[] parts=firstLineOfRequest.split(" ");
        String method=parts[0]; //获得HTTP请求中的请求方式
        String uri=parts[1]; //获得HTTP请求中的uri
//由于get和post提交方式是不同的,下面分情况讨论
        if(method.equalsIgnoreCase("get"))
        {
            /*假定uri="servlet/HelloServlet?username=Tom&password=1234"*/
            //parameters="username=Tom&password=1234"
            String parameters=uri.substring(uri.indexOf("?"),uri.length());

            //parts={"username=Tom","password=1234"};
            parts=parameters.split("&");
            //parts={"username","Tom"};
            parts=parts[0].split("=");
            username=parts[1];

        }else if(method.equalsIgnoreCase("post"))
        {

            int locate=request.indexOf("\r\n\r\n");
            //获得响应正文
            String content=request.substring(locate+4,request.length());
            if(content.indexOf("username=")!=-1){
                /*假定content="username=Tom&password=1234"*/
                //parts={"username=Tom","password=1234"};
                parts=content.split("&");
                //parts={"username","Tom"};
                parts=parts[0].split("=");
                username=parts[1];
            }
        }

        /*创建并发送HTTP响应*/
        //发送HTTP响应第一行
        out.write("HTTP/1.1 200 OK\r\n".getBytes());
        //发送HTTP响应头
        out.write("Content-Type:text/html\r\n\r\n".getBytes());
        
        //发送HTTP响应正文
        String content="<html><head><title>HelloWorld"
                +"</title></head><body>";
        content+="<h1>Hello:"+username+"</h1></body><head>";
        out.write(content.getBytes());


    }

    public static void main(String[] args) {
        String uri="/servlet/myservlet?username=gec&password=1111";

        String parameters=
                uri.substring(uri.indexOf("?"),uri.length());


        //parts={"username=Tom","password=1234"};
        String[] parts= parts=parameters.split("&");
        //parts={"username","Tom"};
        String []parts2=parts[0].split("=");
        String username=parts2[1];
        System.out.println(username);
   *//*     parts=parts[1].split("=");
        String password=parts[1];
        System.out.println(password);*//*

        String []parts3=parts[1].split("=");
        System.out.println(parts3[1]);
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值