本文目录导读:

我来用一个简单的Web服务器案例展示Java的ServerSocket用法。
简单Web服务器实现
import java.io.*;
import java.net.*;
import java.nio.file.*;
import java.util.*;
public class SimpleWebServer {
private static final int PORT = 8080;
private static final String WEB_ROOT = "./webroot";
public static void main(String[] args) {
System.out.println("Simple Web Server starting on port " + PORT + "...");
// 创建webroot目录
new File(WEB_ROOT).mkdirs();
try (ServerSocket serverSocket = new ServerSocket(PORT)) {
System.out.println("Server started. Access http://localhost:" + PORT);
while (true) {
// 等待客户端连接
try (Socket clientSocket = serverSocket.accept()) {
handleClient(clientSocket);
} catch (IOException e) {
System.err.println("Error handling client: " + e.getMessage());
}
}
} catch (IOException e) {
System.err.println("Could not start server: " + e.getMessage());
}
}
private static void handleClient(Socket clientSocket) throws IOException {
String clientAddress = clientSocket.getInetAddress().getHostAddress();
System.out.println("New connection from: " + clientAddress);
// 获取输入输出流
BufferedReader in = new BufferedReader(
new InputStreamReader(clientSocket.getInputStream()));
OutputStream out = clientSocket.getOutputStream();
// 读取HTTP请求
String requestLine = in.readLine();
if (requestLine == null || requestLine.isEmpty()) {
return;
}
System.out.println("Request: " + requestLine);
// 解析请求路径
String[] requestParts = requestLine.split(" ");
String method = requestParts[0];
String path = requestParts.length > 1 ? requestParts[1] : "/";
// 处理GET请求
if ("GET".equals(method)) {
handleGetRequest(path, out);
} else {
sendResponse(out, 405, "Method Not Allowed", "405 Method Not Allowed".getBytes());
}
// 关闭输出流
out.flush();
}
private static void handleGetRequest(String path, OutputStream out) throws IOException {
// 默认首页
if (path.equals("/")) {
path = "/index.html";
}
File file = new File(WEB_ROOT + path);
if (file.exists() && !file.isDirectory()) {
// 文件存在,返回内容
byte[] content = Files.readAllBytes(file.toPath());
String contentType = getContentType(path);
sendResponse(out, 200, "OK", content, contentType);
} else {
// 文件不存在,返回404
String errorMessage = "<html><body><h1>404 Not Found</h1>" +
"<p>The requested resource was not found.</p></body></html>";
byte[] content = errorMessage.getBytes();
sendResponse(out, 404, "Not Found", content, "text/html");
}
}
private static void sendResponse(OutputStream out, int statusCode,
String statusMessage, byte[] content) throws IOException {
sendResponse(out, statusCode, statusMessage, content, "text/html");
}
private static void sendResponse(OutputStream out, int statusCode,
String statusMessage, byte[] content,
String contentType) throws IOException {
// 构建HTTP响应
String header = "HTTP/1.1 " + statusCode + " " + statusMessage + "\r\n" +
"Content-Type: " + contentType + "\r\n" +
"Content-Length: " + content.length + "\r\n" +
"Server: SimpleJavaServer/1.0\r\n" +
"Date: " + new Date() + "\r\n" +
"Connection: close\r\n" +
"\r\n";
out.write(header.getBytes());
out.write(content);
}
private static String getContentType(String path) {
if (path.endsWith(".html") || path.endsWith(".htm")) {
return "text/html";
} else if (path.endsWith(".css")) {
return "text/css";
} else if (path.endsWith(".js")) {
return "application/javascript";
} else if (path.endsWith(".png")) {
return "image/png";
} else if (path.endsWith(".jpg") || path.endsWith(".jpeg")) {
return "image/jpeg";
} else if (path.endsWith(".gif")) {
return "image/gif";
} else if (path.endsWith(".txt")) {
return "text/plain";
} else {
return "application/octet-stream";
}
}
}
测试用的HTML文件
创建 webroot/index.html:
<!DOCTYPE html>
<html>
<head>Simple Java Web Server</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 40px;
background-color: #f0f0f0;
}
.container {
background-color: white;
padding: 20px;
border-radius: 5px;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
}
h1 {
color: #333;
}
.success {
color: green;
}
.info {
background-color: #e7f3fe;
border-left: 6px solid #2196F3;
padding: 10px;
margin: 10px 0;
}
</style>
</head>
<body>
<div class="container">
<h1>Simple Java Web Server</h1>
<p class="success">✓ 服务器运行正常!</p>
<div class="info">
<h2>服务器信息</h2>
<ul>
<li>服务器类型:SimpleJavaServer/1.0</li>
<li>端口:8080</li>
<li>支持的文件类型:HTML, CSS, JavaScript, 图片, 文本文件</li>
</ul>
</div>
<h2>可用页面</h2>
<ul>
<li><a href="/">首页</a></li>
<li><a href="/about.html">关于页面</a></li>
<li><a href="/nonexistent.html">404测试页面</a></li>
</ul>
<p>当前时间:<span id="time"></span></p>
<script>
document.getElementById('time').textContent = new Date().toLocaleString();
</script>
</div>
</body>
</html>
创建 webroot/about.html:
<!DOCTYPE html>
<html>
<head>- Simple Java Web Server</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 40px;
background-color: #f0f0f0;
}
.container {
background-color: white;
padding: 20px;
border-radius: 5px;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
}
</style>
</head>
<body>
<div class="container">
<h1>关于本服务器</h1>
<p>这是一个使用Java ServerSocket实现的简单Web服务器。</p>
<h2>工作原理</h2>
<ol>
<li>使用ServerSocket监听8080端口</li>
<li>接受客户端连接</li>
<li>解析HTTP请求</li>
<li>读取文件并返回HTTP响应</li>
</ol>
<p><a href="/">返回首页</a></p>
</div>
</body>
</html>
使用步骤
-
编译服务器代码:
javac SimpleWebServer.java
-
创建webroot目录并添加HTML文件
-
运行服务器:
java SimpleWebServer
-
访问测试:
- 打开浏览器访问:http://localhost:8080
- 测试其他页面:http://localhost:8080/about.html
- 测试404:http://localhost:8080/nonexistent.html
关键概念解释
- ServerSocket.accept():阻塞等待客户端连接
- HTTP请求解析:读取请求行,获取方法和路径
- 文件读取:从webroot目录读取文件
- HTTP响应:构建包含状态码、头和内容的响应
这个示例展示了Socket编程、HTTP协议基础和文件服务的基本原理。