【JavaWeb】一个简单的Web浏览服务程序
大家天天开心!!!!!
文章目录
- 前言
- 一、一个简单的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 的生动比喻:
你可以把整个网络通信过程想象成一个客服中心的工作流程:
组件 | 比喻 | 职责 |
---|---|---|
| 客服总机 | 它固定在公司的某个电话号码上(绑定端口,比如9999),只负责一件事:等待并接起打进来的电话( |
| 接通后的分机电话 | 当总机 ( |
所以,在我的代码中:
- 1.
ServerSocket serverSocket = new ServerSocket(9999);
就像是:开通了公司的客服总机,号码是9999。 - 2.
Socket socket = serverSocket.accept();
就像是:总机接线员拿起听筒,等待并接起一个客户的来电。一旦电话接通,你就得到了一条和这位客户专用的通话线路(socket
)。 - 3.
客户端(浏览器)通过输入
localhost:9999
来连接,就相当于:客户拨打你公司的总机号码
2.网络通信的“公司大楼”模型
概念 | 现实比喻 | 对应计算机概念 |
---|---|---|
公司大楼 | 一座有固定地址的办公楼 | 你的电脑(主机) |
公司地址 | 办公楼的具体街道门牌号 |
|
客服总机号码 | 公司对外公布的统一电话号码(如400-xxx) | 端口号(如9999) |
客服总机 (ServerSocket) | 前台的总机电话设备(绑定在公司号码上) |
|
客户来电 | 外部客户拨打公司总机号码 | 浏览器访问 |
分机电话 (Socket) | 总机转接给客服人员的专用分机 |
|
客服沟通 | 客服通过分机与客户对话 | 通过 |
重点概念详解
-
localhost
与127.0.0.1
:- •
它们就像你公司的两个别名,都指向同一栋大楼(你的电脑)。
- •
localhost
是域名,127.0.0.1
是IP地址,效果完全一样。就像“环球金融中心”和“浦东新区世纪大道100号”都指同一栋楼。
- •
-
端口号(如9999):
- •
这相当于公司的分机号。一栋大楼(你的电脑)里可以有很多部门(应用程序),每个部门有自己专属的分机号(端口)。
- •
常见端口:
80
(HTTP)、443
(HTTPS)、3306
(MySQL)... 你用的9999
就像给测试部门临时开的分机。
- •
-
ServerSocket
:- •
它不是大楼本身,而是专门负责接听某个分机号(端口)的电话机。
- •
当它
accept()
时,就像前台拿起听筒:“您好,这里是9999号客服,请问有什么可以帮您?”
- •
-
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"));
这行代码做了两件事,涉及到两个类,它们是一种经典的“装饰器模式”的应用:
-
FileReader
(文件读取器):- •
它的角色是“基础工人”。它的任务很简单:负责打开文件,并按顺序一个字符一个字符地读取文件内容。
- •
缺点:如果这个“工人”每读一个字符就要跑去文件那里一次(即频繁进行底层I/O操作),当文件很大时,效率会非常低。
- •
-
BufferedReader
(缓冲读取器):- •
它的角色是“高效的调度员”。它自己不直接读文件,而是站在
FileReader
这个“工人”身边指挥它。 - •
工作原理:它会让
FileReader
一次性多读一些内容(比如读取8KB的数据)到一个缓冲区(可以看作是一个“临时仓库”)里。然后,当你调用bufferedReader.readLine()
时,它就不是慢吞吞地去文件里取,而是飞快地从“临时仓库”里把数据给你。 - •
优点:通过减少直接访问文件(磁盘)的次数,大大提高了读取效率,尤其是在读取大文件时。
它还提供了非常方便的readLine()
方法,可以直接读取一整行文本。
- •
所以,new BufferedReader(new FileReader(...))
这种套娃式的写法,意思就是:我想用一个高效的、带缓冲的读取器 (BufferedReader
),来读取一个文件 (FileReader
)。
总结
这就是一个简单的模拟的Web服务程序,大家可以自己试试模拟一下,了解浏览器和服务器是如何交互的,我会持续更新的,谢谢大家。