一.实验目的和意义
(1) 处理一个 http 请求
(2) 接收并解析 http 请求
(3) 从服务器文件系统中获得被请求的文件
(4) 创建一个包括被请求的文件的 http 响应信息
(5) 直接发送该信息到客户端 通过本实验,使学生能够进一步理解 HTTP 协议的技术细节以及 WEB 服务器的实现原理
二.实验过程
(1)前期准备
两个 java 代码文件,分别命名为:“HttpRequest.java”和“WebServer.java”。
两个带跳转的测试网页“index.html”和“next.html”以及其各自包含的图片“1.jpg”和“2.jpg” HttpRequest.java 的主要功能为:获取 http 请求中的套接字的输入流和输出流,即完成“对 从服务器端发回的数据流”和“将要发送到服务器端的数据流”的处理和输出。
WebServer.java 的主要功能为:创建线程,连续创建套接字以及处理 http 请求。
(2)测试阶段
我们使用 jdk 的 javac 指令对 java 代码进行编译,然后启动服务器的默认端口 8080(代码中 预设),然后在 EDGE 浏览器中对各种情况进行测试和检测输出,具体步骤如下。
1.首先我们在 cmd 中,利用 javac 命令编译 main 方法所在的 Java 文件“WebServer.java”,启 动服务器,具体如下:
2.在浏览器中需要输入网址“localhost:8080/index.html”,页面显示和终端输出情况如下:
3.点击 NEXT PAGE TEST,页面显示和终端输出情况如下:
4. 测 试 一 下 错 误 路 径 的 文 件 访 问 结 果 , 在 浏 览 器 中 输 入 一 个 错 误 的 网 址 如 “localhost:8888/123.html”,页面显示和终端输出如下:
经过运行及验证,该 web 服务器的功能正常。
三.实验分析和总结
1.遇到的问题
1) 运行 java 文件和打开 html 文件时会出现乱码,应该在文件保存时将编码改为 ANSI。
2) java 文件名要和类名相同(没学 java 好懵 oo)
3) 两个 html 文件中的地址设为绝对地址就找不到界面了,改成相对地址就能成功运行, 不知道为什么。。。
2.收获与心得
通过本次实验,加深了我对基于 HTTP 协议的客户/服务器模式的信息交换分四个过程建立连接、发送请求信息、发送响应信息、关闭连接以及 WEB 服务器的实现原理的理解,以及学习了如何编写 html 网页。
四、代码附录
/*index.html*/<!DOCTYPE html><html> <head> <TITLE>Java Web 服务器</TITLE> <h1>Windows 环境下用 java 实现 Web 服务器实验-学号</h1> </head> <body> <h2>NETWORK HOMEWORK</h2> <a href="http://localhost:8888/next.html">NEXT PAGE TEST</a> <body background="images/1.jpg"></body></html>
/*next.html*/<!DOCTYPE html><head> <TITLE>Java Web 服务器</TITLE> <h1>Windows 环境下用 java 实现 Web 服务器实验-学号</h1></head><body><h2>This is the second page</h2><a href="http://localhost:8888/index.html">back <body background="images/2.jpg"></body> </html>
/*WebServer.java*/import java.io.* ;import java.net.* ;import java.util.* ;public final class WebServer { public static void main(String argv[]) throws Exception { int port=8888; // 建立一个套接字 ServerSocket socket = new ServerSocket(port); while (true) { // 监听一个tcp连接的request. Socket connection = socket.accept(); // 处理HTTP请求消息。 HttpRequest request = new HttpRequest(connection); // 建立一个线程处理请求 Thread thread = new Thread(request); thread.start(); } }}
/*HttpRequest.java*/import java.io.* ;import java.net.* ;import java.util.* ;final class HttpRequest implements Runnable { final static String CRLF = "/r/n"; Socket socket; public HttpRequest(Socket socket) throws Exception { this.socket = socket; } public void run() { try { processRequest(); } catch (Exception e) { System.out.println(e); } } private void processRequest() throws Exception { InputStream is = socket.getInputStream(); DataOutputStream os = new DataOutputStream(socket.getOutputStream()); BufferedReader br = new BufferedReader(new InputStreamReader(is)); // 获取http的request信息 String requestLine = br.readLine(); // 从请求行中提取文件信息 StringTokenizer tokens = new StringTokenizer(requestLine); tokens.nextToken(); // GET之后为文件名 String fileName = tokens.nextToken(); fileName = "." + fileName ; FileInputStream fis = null ; boolean fileExists = true ; //判断文件是否查询到 try { fis = new FileInputStream(fileName); } catch (FileNotFoundException e) { fileExists = false ; } //测试输出 System.out.println("/n*************Request**************/n"); System.out.println(requestLine); String headerLine = null; while ((headerLine = br.readLine()).length() != 0) { System.out.println(headerLine); } // 构造response信息 String statusLine = null; String contentTypeLine = null; String entityBody = null; if (fileExists) { //执行成功的话返回“200 OK” statusLine = "HTTP/1.0 200 OK" + CRLF; contentTypeLine = "Content-Type: "+contentType(fileName) + CRLF; } else { //执行失败,文件未找到的时候返回“404 File Not Found” statusLine = "HTTP/1.0 404 File Not Found" + CRLF; contentTypeLine = "Content-Type: text/html" + CRLF; entityBody = "<HTML>" + "<HEAD><TITLE>Not Found</TITLE></HEAD>" + "<P>File name:</P>"+fileName+ "<BODY>404 Not Found</BODY></HTML>"; } // 将上述返回值依次输出 os.writeBytes(statusLine); os.writeBytes(contentTypeLine); os.writeBytes(CRLF); System.out.println("/n*************Response**************/n"); System.out.println(statusLine); if (fileExists) { sendBytes(fis, os); fis.close(); } else { os.writeBytes(entityBody) ; } // 结束关闭 os.close(); br.close(); socket.close(); } private static void sendBytes(FileInputStream fis, OutputStream os) throws Exception { byte[] buffer = new byte[1024]; int bytes = 0; while ((bytes = fis.read(buffer)) != -1) { os.write(buffer, 0, bytes); } } private static String contentType(String fileName) { if(fileName.endsWith(".htm") || fileName.endsWith(".html")) { return "text/html"; } else return "other Content-type" ; }}