【JavaWeb】一个简单的Web浏览服务程序

发布于:2025-09-09 ⋅ 阅读:(28) ⋅ 点赞:(0)

大家天天开心!!!!!

文章目录

  • 前言
  • 一、一个简单的Web浏览服务程序
  • 二、对以上代码的解释:
    • 1.ServerSocket和Socket的生动比喻:
    • 2.网络通信的“公司大楼”模型
    • 重点概念详解
    • 常见端口号及其用途
  • 三、BufferedReader 和 FileReader 的角色
  • 总结


前言

     在我们学习TomCat和Servlet之前,我们要知道Tomcat其实就相互于一个Java程序,但是这个Java程序可以处理来自浏览器的Http请求。下面我们就自己来编写一个“服务器”来接收和相应浏览器或客户端发送的请求。


提示:以下是本篇文章正文内容,下面案例可供参考

一、一个简单的Web浏览服务程序

    下面是源代码:

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class MyTomcat {
    public static void main(String[] args) {
        try (ServerSocket serverSocket = new ServerSocket(9999)) {
            System.out.println("=====我的 web 服务在 9999 端口监听=====");

            while (!serverSocket.isClosed()) {
                try (Socket socket = serverSocket.accept();
                     OutputStream outputStream = socket.getOutputStream();
                     BufferedReader bufferedReader =
                             new BufferedReader(new FileReader("src/hello.html"))) {

                    // 发送HTTP响应头
                    String httpHeader = "HTTP/1.1 200 OK\r\n" +
                            "Content-Type: text/html; charset=utf-8\r\n" +
                            "\r\n";
                    outputStream.write(httpHeader.getBytes());

                    // 发送HTML内容
                    String line;
                    while ((line = bufferedReader.readLine()) != null) {
                        outputStream.write(line.getBytes());
                    }

                } catch (IOException e) {
                    System.out.println("处理客户端请求时出错: " + e.getMessage());
                }
            }
        } catch (IOException e) {
            System.out.println("启动服务器失败: " + e.getMessage());
            // 检查端口是否被占用[1,3](@ref)
            System.out.println("请确认9999端口没有被其他程序占用");
        }
    }
}

二、对以上代码的解释:

            首先先说明我这个是模拟的普通Web服务程序,让我们来看看Web服务器如何与浏览器“对话”是如何进行的

     

    1.ServerSocket 和 Socket 的生动比喻:

           你可以把整个网络通信过程想象成一个​​客服中心​​的工作流程:

组件

比喻

职责

ServerSocket

​客服总机​

它固定在公司的某个电话号码上(​​绑定端口​​,比如9999),只负责一件事:​​等待并接起打进来的电话​​(accept()方法)。它本身不处理具体业务。

Socket

​接通后的分机电话​

当总机 (ServerSocket) 接起一个来电后,它会为这个通话​​创建一条专用的分机线路​​(一个新的Socket对象)。客服通过这部​​分机电话​​与客户进行​​双向的、具体的沟通​​(数据交换)。​​服务器端和客户端各有一部这样的“电话”​​。

所以,在我的代码中:

  • 1.

    ServerSocket serverSocket = new ServerSocket(9999);就像是:​​开通了公司的客服总机,号码是9999​​。

  • 2.

    Socket socket = serverSocket.accept();就像是:​​总机接线员拿起听筒,等待并接起一个客户的来电。一旦电话接通,你就得到了一条和这位客户专用的通话线路(socket)​​。

  • 3.

    客户端(浏览器)通过输入 localhost:9999来连接,就相当于:​​客户拨打你公司的总机号码​

      2.网络通信的“公司大楼”模型

概念

现实比喻

对应计算机概念

​公司大楼​

一座有固定地址的办公楼

你的电脑(主机)

​公司地址​

办公楼的具体街道门牌号

localhost或 127.0.0.1(本机地址)

​客服总机号码​

公司对外公布的统一电话号码(如400-xxx)

端口号(如9999)

​客服总机 (ServerSocket)​

前台的总机电话设备(绑定在公司号码上)

ServerSocket serverSocket = new ServerSocket(9999);

​客户来电​

外部客户拨打公司总机号码

浏览器访问 http://localhost:9999

​分机电话 (Socket)​

总机转接给客服人员的专用分机

Socket socket = serverSocket.accept();

​客服沟通​

客服通过分机与客户对话

通过 socket.getInputStream()/getOutputStream()读写数据

重点概念详解

  1.  

    localhost与 127.0.0.1​:

    • 它们就像你公司的​​两个别名​​,都指向同一栋大楼(你的电脑)。

    • localhost是域名,127.0.0.1是IP地址,效果完全一样。就像“环球金融中心”和“浦东新区世纪大道100号”都指同一栋楼。

  2.  

    ​端口号(如9999)​​:

    • 这相当于公司的​​分机号​​。一栋大楼(你的电脑)里可以有很多部门(应用程序),每个部门有自己专属的分机号(端口)。

    • 常见端口:80(HTTP)、443(HTTPS)、3306(MySQL)... 你用的9999就像给测试部门临时开的分机。

  3.  

    ServerSocket​:

    • 它​​不是​​大楼本身,而是​​专门负责接听某个分机号(端口)的电话机​​。

    • 当它 accept()时,就像前台拿起听筒:“您好,这里是9999号客服,请问有什么可以帮您?”

  4.  

    Socket​:

    • 这是​​接通后建立的专用通信通道​​。想象客服代表拿起分机:“王先生您好,我是您的专属客服小李,您的问题请讲...”

    • 每个客户端连接都会创建一个新的 Socket对象(就像每个来电都转接给一个新的客服代表)。

       端口是计算机网络中一个非常基础且重要的概念。它就像是计算机与外界通信的“门户”或“通道”,用来区分一台计算机上不同的网络应用程序或服务

       

为了更具体地理解,这里有一个经典的比喻:

  •  

    ​IP 地址​​:相当于​​一栋大楼的地址​​(如:上海市浦东新区张江高科技园区博云路2号)。它唯一标识了网络上的某一台设备(计算机、服务器等)

  •  

    ​端口号​​:相当于这栋大楼里​​每个房间的门牌号​​(如:301室、302室)。它唯一标识了这台设备上运行的不同网络程序或服务

数据包通过IP地址找到目标计算机后,再通过端口号就能知道自己应该被哪个具体的应用程序(如浏览器、游戏、邮箱客户端)接收和处理,从而实现“多任务并行”和“精准投递”。

类别

端口号范围

用途

常见示例

​知名端口​

0 - 1023

预留给最通用的网络服务,由国际组织IANA分配和管理。

​80​​: HTTP (网页浏览)


​443​​: HTTPS (加密网页浏览)
​21​​: FTP (文件传输)
​22​​: SSH (安全远程登录)
​25​​: SMTP (发送邮件)

​注册端口​

1024 - 49151

松散地绑定于一些服务,许多用户或企业程序可以注册使用这些端口。

​3306​​: MySQL数据库


​3389​​: Windows远程桌面(RDP)
​5432​​: PostgreSQL数据库

动态/私有端口​

49152 - 65535

通常由客户端程序临时使用,操作系统会动态分配。

当你用浏览器访问网站时,你的电脑就会用一个此范围内的端口去连接服务器的80或443端口。

常见端口号及其用途

了解一些常见端口号有助于你理解日常的网络活动和服务配置:

端口号

协议

用途简述

​20/21​

FTP

​文件传输协议​​(数据/控制)

​22​

SSH

​安全外壳协议​​,用于加密远程管理

​23​

Telnet

​远程登录协议​​(明文传输,不安全)

​53​

DNS

​域名系统​​,将域名解析为IP地址

​67/68​

DHCP

​动态主机配置协议​​,自动分配IP地址

​80​

HTTP

​超文本传输协议​​,用于网页浏览

​110​

POP3

​邮局协议版本3​​,用于接收邮件

​143​

IMAP

​互联网消息访问协议​​,用于接收邮件

​443​

HTTPS

​安全超文本传输协议​​,加密的网页浏览

​3306​

MySQL

​MySQL数据库​​服务

​3389​

RDP

​远程桌面协议​​,用于Windows远程控制

 

 三、BufferedReader 和 FileReader 的角色

BufferedReader bufferedReader = new BufferedReader(new FileReader("src/hello.html"));

     

这行代码做了两件事,涉及到两个类,它们是一种经典的​​“装饰器模式”​​的应用:

  1.  

    FileReader(文件读取器)​​:

    • ​它的角色是“基础工人”​​。它的任务很简单:负责打开文件,并按顺序一个字符一个字符地读取文件内容。

    • ​缺点​​:如果这个“工人”每读一个字符就要跑去文件那里一次(即频繁进行底层I/O操作),当文件很大时,效率会非常低。

  2.  

    BufferedReader(缓冲读取器)​​:

    • ​它的角色是“高效的调度员”​​。它自己不直接读文件,而是​​站在 FileReader这个“工人”身边指挥它​​。

    • ​工作原理​​:它会让 FileReader​一次性多读一些内容​​(比如读取8KB的数据)到一个​​缓冲区​​(可以看作是一个“临时仓库”)里。然后,当你调用 bufferedReader.readLine()时,它就不是慢吞吞地去文件里取,而是​​飞快地从“临时仓库”里把数据给你​​。

    • ​优点​​:通过​​减少直接访问文件(磁盘)的次数​​,大大提高了读取效率,尤其是在读取大文件时。

      它还提供了非常方便的 readLine()方法,可以直接读取一整行文本。

所以,new BufferedReader(new FileReader(...))这种套娃式的写法,意思就是:​​我想用一个高效的、带缓冲的读取器 (BufferedReader),来读取一个文件 (FileReader)​​。


总结

    这就是一个简单的模拟的Web服务程序,大家可以自己试试模拟一下,了解浏览器和服务器是如何交互的,我会持续更新的,谢谢大家。


网站公告

今日签到

点亮在社区的每一天
去签到