Java Web基础(一)

173 阅读9分钟

概念图

Java Web基础(一).png

B/S体系架构

B/S体系架构,即浏览器/服务器(Browser/Server)架构,是一种软件架构模式。它与传统的C/S(客户机/服务器,Client/Server)架构相对。B/S架构的主要特点包括:

1. 架构概述

  • 浏览器端:用户通过Web浏览器访问应用程序,无需安装专用客户端软件。所有用户界面的渲染和操作都在浏览器中进行。
  • 服务器端:服务器负责处理业务逻辑、数据存储和管理,然后将结果以HTML等格式反馈给浏览器。

2. 主要组成部分

  1. 浏览器:用户通过浏览器发送HTTP请求,显示Web页面,提供用户交互界面。
  2. Web服务器:接收来自浏览器的请求,处理请求后,返回相应的数据。常用的Web服务器有Apache、Nginx等。
  3. 应用服务器:处理复杂的业务逻辑,通常与Web服务器搭配使用。常见的应用服务器包括Tomcat、JBoss等。
  4. 数据库服务器:存储和管理应用中的数据,通过数据库管理系统(如MySQL、PostgreSQL)与应用服务器进行交互。

C/S体系架构

C/S体系架构,即客户机/服务器(Client/Server)架构,是一种常见的软件架构模式。在这种架构中,应用程序分为两部分:客户端和服务器端。以下是C/S架构的详细介绍:

1. 架构概述

  • 客户端:客户机是用户与系统交互的界面,负责展示数据、接收用户输入并发送请求给服务器。客户端通常运行在用户的计算机上,可以是桌面应用程序或移动应用程序。
  • 服务器端:服务器负责处理客户端的请求、执行业务逻辑、存储和管理数据,并将处理结果返回给客户端。服务器通常具有较强的处理能力和存储能力。

2. 主要组成部分

  1. 客户端程序:用户使用的应用程序,常常需要在每台客户机上进行安装。客户端负责用户界面的呈现、用户输入的收集及与服务器的通信。
  2. 服务器程序:提供服务的后台程序,处理来自客户端的请求,与数据库进行交互并返回数据。
  3. 数据库:许多C/S架构的应用程序还会涉及一个数据库系统,用于存储和管理应用数据。数据库通常在服务器端。

3. 特点

  • 资源利用:C/S架构可以充分利用客户端和服务器各自的资源。客户端可以处理用户界面和部分计算,服务器可以处理复杂的计算和数据存储。
  • 高性能:由于许多处理发生在客户端,服务器的负载会相对较轻,从而提高了整体性能。
  • 复杂性:C/S架构的设计和开发可能比较复杂,因为需要处理客户端和服务器之间的通信以及数据一致性问题。
  • 维护:客户端需要在每台计算机上进行安装和维护,更新时常常需要手动操作,增加了维护的难度。
  • 更强的交互性:相比B/S架构,C/S架构能提供更丰富的用户界面和更高的交互性,适合对性能和用户体验要求较高的应用。

4. 应用场景

C/S架构适用于以下类型的应用:

  • 企业内部系统(如ERP、CRM)
  • 桌面应用程序(如图形设计软件、会计软件等)
  • 即时通讯软件(如QQ、Skype等)
  • 游戏客户端(如MMORPG等)

3. 特点

  • 无客户端安装:用户只需要一个浏览器就可以访问应用,降低了用户使用的门槛。
  • 跨平台:不同操作系统的用户都可以使用相同的应用,只要有浏览器支持即可。
  • 易于更新和维护:应用的更新和维护集中在服务器端,用户获取最新版本不需要手动更新客户端。
  • 可扩展性:基于Web的应用易于扩展,可以通过负载均衡等方式应对大量用户请求。
  • 网络友好:B/S架构便于在网络环境中运行,能够更好地支持分布式应用。

4. 应用场景

B/S架构适用于许多类型的应用,包括:

  • 企业管理系统(ERP、CRM等)
  • 在线购物网站
  • 社交媒体平台
  • 内容管理系统(CMS)
  • 在线教育平台

HTTP传输

image.png

InetAddress 获取本地址

import java.net.InetAddress;
import java.net.UnknownHostException;

public class LocalIp {
    public static void main(String[] args) throws UnknownHostException {
        InetAddress inetAddress = InetAddress.getLocalHost();
        // 获取当前ip地址
        System.out.println(inetAddress.getHostAddress());
        // 获取主机名称
        String hostName = inetAddress.getHostName();
        System.out.println(hostName);
    }
}

DNS域名解析过程图解

image.png

1. DNS的基本概念

  • 域名:是互联网上用于标识网络地址的字符串,例如 www.example.com
  • IP地址:是数字格式,用于标识互联网上的设备,例如 192.168.1.1

2. DNS域名解析的过程

DNS域名解析过程通常分为以下几个步骤:

  1. 查询请求:用户在浏览器中输入一个域名,例如 www.example.com。浏览器检查本地缓存,以查看是否已记录该域名的IP地址。
  2. 递归查询:如果本地缓存中没有记录,浏览器会向配置的DNS服务器发送查询请求。如果是递归DNS服务器,它将代为查询。
  3. 根DNS服务器:如果递归DNS服务器无法找到该域名,它会首先询问根DNS服务器。根DNS服务器知道各个顶级域名DNS服务器的地址(如 .com.org 等)。
  4. 顶级域名DNS服务器:根服务器会将请求转发给相应的顶级域名DNS服务器,例如.com域名的服务器。这个服务器会提供该域名的授权DNS服务器的地址。
  5. 授权DNS服务器:递归DNS服务器接下来向提供该域名的授权DNS服务器发起请求。这个服务器保存该域名的详细记录,包括其对应的IP地址。
  6. 获取IP地址:授权DNS服务器查找IP地址,并将其返回给递归DNS服务器。
  7. 响应回客户机:最后,递归DNS服务器将获得的IP地址返回给用户的浏览器,浏览器将使用该IP地址与目标服务器建立连接。
  8. 缓存结果:为了提升性能,浏览器和DNS服务器会将解析的结果进行缓存,以便将来查询时可以直接使用。

UDP 协议

UDP是一种简单的、面向数据报的协议,允许应用程序在网络上传输数据。它不保证数据的可靠性、顺序或完整性,主要用于需要快速传输和低延迟的场合,例如视频流、在线游戏和实时语音通信。

特点: 面向无连接、不可靠的协议、安全系统低、容易丢包 但是传输速度非常快 不需要 tcp的三次握手。

适用场景

  • UDP特别适合用于对丢包不敏感的应用,比如:

    • 实时音视频传输(如VoIP、视频会议)
    • 在线游戏
    • DHCP(动态主机配置协议)
    • DNS(域名系统)查询

Tcp的三次握手和四次挥手

image.png

一、三次握手(TCP连接建立)

三次握手用于在客户端和服务器之间建立可靠的TCP连接。过程如下:

  1. 第一次握手(SYN)

    • 客户端服务器发送一个SYN包,请求建立连接,并随机选择一个序列号(ISN)。

    • 客户端 ---- SYN ----> 服务器

  2. 第二次握手(SYN-ACK)

    • 服务器收到SYN包后,回应一个SYN-ACK包,表示同意连接,并为自身生成ISN,同时确认收到客户端的序列号(客户端的ISN + 1)。

    • 服务器 <---- SYN-ACK ---- 客户端

  3. 第三次握手(ACK)

    • 客户端收到SYN-ACK包后,发送一个ACK包回服务器,确认收到服务器的SYN-ACK包(服务器的ISN + 1)。

    • 客户端 ---- ACK ----> 服务器

经过这三次握手后,客户端和服务器之间的TCP连接建立完成,进入数据传输阶段。

二、四次挥手(TCP连接终止)

四次挥手用于在TCP连接中断时安全地关闭连接。过程如下:

  1. 第一次挥手(FIN)

    • 客户端服务器发送一个FIN包,表示客户端要关闭连接。

    • 客户端 ---- FIN ----> 服务器

  2. 第二次挥手(ACK)

    • 服务器收到FIN包后,回应一个ACK包,确认收到客户端的FIN包。

    • 服务器 <---- ACK ---- 客户端

  3. 第三次挥手(FIN)

    • 服务器准备关闭连接时,向客户端发送一个FIN包,表示服务器也要关闭连接。

    • 服务器 ---- FIN ----> 客户端

  4. 第四次挥手(ACK)

    • 客户端收到服务器的FIN包后,发送一个ACK包回服务器,确认收到FIN包。

    • 客户端 <---- ACK ---- 服务器

至此,双方的TCP连接正式关闭。

总结

  • 三次握手:用于建立连接,确保双方都能接收和发送数据。
  • 四次挥手:用于安全地关闭连接,确保双方都能正常终止通信。

TCP协议发送数据

import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;

public class TcpClient {
    public static void main(String[] args) throws IOException {
        // 修改 IP 地址为服务器的实际 IP 地址
        String serverIp = "192.168.1.107"; // 示例 IP 地址
        int port = 8888;

        // 创建 Socket 连接到服务器
        try (Socket socket = new Socket(serverIp, port)) {
            // 获取输出流
            OutputStream outputStream = socket.getOutputStream();

            // 创建 PrintWriter 对象
            try (PrintWriter printWriter = new PrintWriter(outputStream, true)) {
                // 发送数据
                printWriter.println("hello world");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
   

TCP协议接收数据

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

public class TcpServer {
    public static void main(String[] args) throws IOException {
        /*
        * 1.创建一个服务器端Socket,即ServerSocket,指定绑定的端口,并监听此端口
        * 获取输入流对象
        * 获取数据
        * 输出数据
        * 释放资源
        * */
        ServerSocket serverSocket = new ServerSocket(8888);

        System.out.println("-----Server-----");
        Socket  socket = serverSocket.accept();
        System.out.println("一个客户端建立了连接");
        System.out.println(socket.getInetAddress()+":"+socket.getPort());

        InputStream inputStream = socket.getInputStream();
        byte[] b = new byte[1024];
        int len = inputStream.read(b);
        String data = new String(b,0,len);
        System.out.println("data:"+data);

        socket.close();
        serverSocket.close();
        System.out.println("-----服务端退出-----");
    }
}

手写http服务器端

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class HttpTcpServer {
    public static void main(String[] args) throws IOException {
        // 创建http  tcp服务器 访问静态资源 默认是80端口 在浏览器是不需要写的
        ServerSocket serverSocket =  new ServerSocket(80);
        // 死循环
        while (true){
            System.out.println("等待客户端发送数据---HttpTcpServer");
            // 监听客户端发送给服务端数据 等待阻塞 获取客户端发送给服务器的数据
            Socket socket = serverSocket.accept();

            // 创建线程
            new Thread(new Runnable() {
                @Override
                public void run() {
                    OutputStream outputStream = null;
                    try {
                        // 浏览器 -> 服务器端
                        outputStream = socket.getOutputStream();
                        // 程序读取本地磁盘静态文件到内存中
                        File file = new File("E:\testHtml\jsd.html");
                        FileInputStream fileInputStream = new FileInputStream(file);
                        byte[] bytes = new byte[1024];
                        int len = fileInputStream.read(bytes);
                        // 从内存中将该数据发送给浏览器
                        outputStream.write(bytes, 0, len);
                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally {
                        try {
                            // 关闭资源
                            if(outputStream != null){
                                outputStream.close();
                            }
                            if(socket != null){
                                socket.close();
                            }
                        } catch (Exception e){
                            e.printStackTrace();
                        }
                    }
                }
            }).start();
        }
    }
}