JDK21 揭秘网络编程利器:用 TCP 构建服务器
2023-10-04 13:02:31
网络编程是后端开发领域的必修课,而 HTTP 服务器则是 Web 开发的核心。本小册将以 JDK8 到 JDK21 发布的新语法特性为基础,从头开始构建一个基于 TCP 协议的网络框架!
借助这些新特性,我们可以使用更简洁、更具表现力的代码,打造一个强大的网络框架。
小册主要内容:
- 构建一个 TCP 服务器
- 了解 HTTP 协议的运作方式
- 实现常见 HTTP 方法(GET、POST 等)
- 使用 HTTPS 保护数据安全
- 部署服务器并进行测试
基础篇:TCP 服务器从零搭建
我们从最基础的 TCP 服务器搭建开始。首先,我们来了解一下 TCP 协议。
TCP(Transmission Control Protocol)是一种面向连接的、可靠的传输层协议,它可以确保数据在网络上可靠地传输。TCP 在数据传输前会先建立连接,并在数据传输过程中对数据进行校验,如果发现错误就会重新发送数据。
为了构建一个 TCP 服务器,我们需要:
- 创建一个套接字(Socket)对象。
- 将套接字绑定到一个端口。
- 监听套接字上的连接请求。
- 接受连接请求,并创建一个新的套接字对象来处理该连接。
我们可以使用 Java 的 ServerSocket
和 Socket
类来实现这些操作。下面是一个简单的 TCP 服务器示例:
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class TcpServer {
public static void main(String[] args) throws IOException {
// 创建一个ServerSocket对象,并将其绑定到端口8080
ServerSocket serverSocket = new ServerSocket(8080);
// 监听ServerSocket上的连接请求
while (true) {
// 接受连接请求,并创建一个新的Socket对象来处理该连接
Socket socket = serverSocket.accept();
// 处理连接请求,例如读取数据、发送数据等
// ...
// 关闭Socket对象
socket.close();
}
// 关闭ServerSocket对象
serverSocket.close();
}
}
进阶篇:HTTP 服务器构建
在了解了 TCP 服务器的基本原理后,我们可以进一步构建一个 HTTP 服务器。
HTTP(Hypertext Transfer Protocol)是一种用于在万维网上进行数据传输的协议,它规定了客户端和服务器之间如何交换数据。HTTP 服务器需要能够处理 HTTP 请求,并根据请求返回相应的响应。
要构建一个 HTTP 服务器,我们需要:
- 创建一个 TCP 服务器。
- 解析 HTTP 请求。
- 根据 HTTP 请求生成响应。
- 将响应发送给客户端。
我们可以使用 Java 的 HttpServer
类来简化 HTTP 服务器的构建。HttpServer
类提供了许多便捷的方法,可以帮助我们轻松地处理 HTTP 请求和响应。
下面是一个简单的 HTTP 服务器示例:
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpServer;
public class HttpServer {
public static void main(String[] args) throws IOException {
// 创建一个HttpServer对象,并将其绑定到端口8080
HttpServer server = HttpServer.create(new InetSocketAddress(8080), 0);
// 设置请求处理程序
server.createContext("/", new HttpHandler() {
@Override
public void handle(HttpExchange exchange) throws IOException {
// 解析HTTP请求
String requestMethod = exchange.getRequestMethod();
String requestURI = exchange.getRequestURI().toString();
Map<String, String> requestHeaders = getRequestHeaders(exchange);
String requestBody = getRequestBody(exchange);
// 生成HTTP响应
String responseBody = "Hello World!";
byte[] responseBytes = responseBody.getBytes(StandardCharsets.UTF_8);
int responseCode = HttpURLConnection.HTTP_OK;
Map<String, String> responseHeaders = new HashMap<>();
responseHeaders.put("Content-Type", "text/plain");
// 发送HTTP响应
exchange.sendResponseHeaders(responseCode, responseBytes.length);
exchange.getResponseBody().write(responseBytes);
exchange.close();
}
});
// 启动HTTP服务器
server.start();
}
private static Map<String, String> getRequestHeaders(HttpExchange exchange) {
Map<String, String> headers = new HashMap<>();
for (Map.Entry<String, List<String>> entry : exchange.getRequestHeaders().entrySet()) {
headers.put(entry.getKey(), entry.getValue().get(0));
}
return headers;
}
private static String getRequestBody(HttpExchange exchange) throws IOException {
InputStreamReader isr = new InputStreamReader(exchange.getRequestBody(), StandardCharsets.UTF_8);
BufferedReader br = new BufferedReader(isr);
StringBuilder sb = new StringBuilder();
String line;
while ((line = br.readLine()) != null) {
sb.append(line);
}
br.close();
isr.close();
return sb.toString();
}
}
这个 HTTP 服务器可以处理 GET 请求,并返回一个简单的“Hello World!”响应。我们可以通过在浏览器中输入 http://localhost:8080
来访问这个服务器。
高阶篇:HTTPS 安全防护
为了确保数据传输的安全性,我们可以使用 HTTPS(Hypertext Transfer Protocol Secure)协议。HTTPS 是 HTTP 的安全版本,它通过使用加密技术来保护数据在网络上的传输。
要构建一个 HTTPS 服务器,我们需要:
- 生成一个 SSL 证书。
- 将 SSL 证书导入到服务器。
- 配置服务器使用 SSL 证书。
我们可以使用 Java 的 KeyStore
和 SSLContext
类来实现这些操作。下面是一个简单的 HTTPS 服务器示例:
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.nio.charset.StandardCharsets;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.util.HashMap;
import java.util.Map;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLServerSocketFactory;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpServer;
public class HttpsServer {
public static void main(String[] args) throws IOException, KeyStoreException, NoSuchAlgorithmException, UnrecoverableKeyException, KeyManagementException {
// 加载SSL证书
KeyStore keyStore = KeyStore.getInstance("JKS");
keyStore.load(new FileInputStream("mykeystore.jks"), "password".toCharArray());
// 创建KeyManagerFactory对象
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
keyManagerFactory.init(keyStore, "password".toCharArray());
// 创建SSLContext对象
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(keyManagerFactory.getKeyManagers(), null, null);
// 创建SSLServerSocketFactory对象
SSLServerSocketFactory sslServerSocketFactory = sslContext.getServerSocketFactory();
// 创建一个HttpServer对象,并将其绑定到端口8443
HttpServer server = HttpServer.create(new InetSocketAddress(8443), 0);
// 设置请求处理程序
server.createContext("/", new HttpHandler() {
@Override
public void handle(HttpExchange exchange) throws IOException {
// 解析HTTP请求
String requestMethod =