← 返回目录

第五章:网络连接

构建 HTTP 服务与客户端通信

1. 原生 HTTP 服务器

Node.js 内置的 http 模块可以直接创建 HTTP 服务器,无需任何第三方依赖。

import http from "http";

interface ApiResponse {
    status: string;
    message: string;
    timestamp: number;
}

const server = http.createServer((req, res) => {
    const url = new URL(req.url ?? "/", `http://${req.headers.host}`);

    if (url.pathname === "/api/health" && req.method === "GET") {
        const body: ApiResponse = {
            status: "ok",
            message: "服务运行中",
            timestamp: Date.now(),
        };
        res.writeHead(200, { "Content-Type": "application/json" });
        res.end(JSON.stringify(body));
    } else {
        res.writeHead(404, { "Content-Type": "text/plain" });
        res.end("Not Found");
    }
});

server.listen(3000, () => {
    console.log("服务器已启动: http://localhost:3000");
});
🔄 对比 Java:原生 HTTP 服务器类似 com.sun.net.httpserver.HttpServer,但 API 更简洁。实际项目中通常使用 Express 等框架,就像 Java 用 Spring Boot。

2. Express.js 基础

Express 是 Node.js 最流行的 Web 框架,极简且灵活。

npm install express
npm install -D @types/express
import express, { Request, Response } from "express";

interface Todo {
    id: number;
    title: string;
    done: boolean;
}

const app = express();
app.use(express.json()); // 解析 JSON 请求体

const todos: Todo[] = [];
let nextId = 1;

// GET - 获取所有待办
app.get("/api/todos", (_req: Request, res: Response) => {
    res.json(todos);
});

// POST - 创建待办
app.post("/api/todos", (req: Request, res: Response) => {
    const todo: Todo = { id: nextId++, title: req.body.title, done: false };
    todos.push(todo);
    res.status(201).json(todo);
});

// PUT - 更新待办
app.put("/api/todos/:id", (req: Request, res: Response) => {
    const todo = todos.find((t) => t.id === Number(req.params.id));
    if (!todo) return res.status(404).json({ error: "未找到" });
    Object.assign(todo, req.body);
    res.json(todo);
});

// DELETE - 删除待办
app.delete("/api/todos/:id", (req: Request, res: Response) => {
    const idx = todos.findIndex((t) => t.id === Number(req.params.id));
    if (idx === -1) return res.status(404).json({ error: "未找到" });
    todos.splice(idx, 1);
    res.status(204).send();
});

app.listen(3000, () => console.log("Express 服务已启动"));

3. Express 中间件

中间件是 Express 的核心概念——每个请求按顺序流过中间件链,每层可以处理、修改或拦截请求。

import express, { Request, Response, NextFunction } from "express";

const app = express();

// 内置中间件
app.use(express.json());                    // 解析 JSON body
app.use(express.urlencoded({ extended: true })); // 解析表单
app.use(express.static("public"));          // 静态文件服务

// 自定义日志中间件
function logger(req: Request, _res: Response, next: NextFunction): void {
    console.log(`[${new Date().toISOString()}] ${req.method} ${req.url}`);
    next(); // 必须调用 next(),否则请求会挂起
}
app.use(logger);

// 错误处理中间件(4个参数)
function errorHandler(
    err: Error, _req: Request, res: Response, _next: NextFunction
): void {
    console.error("服务器错误:", err.message);
    res.status(500).json({ error: "内部服务器错误" });
}
app.use(errorHandler);
🔄 与 Python Flask/Django 的对比:Express 的中间件模式类似 Python WSGI/ASGI 中间件。Express 更轻量,类似 Flask 的极简风格,而非 Django 的全栈框架。

常用第三方中间件:cors(跨域)、helmet(安全头)、morgan(HTTP 日志)。

4. HTTP 客户端

Node.js 18+ 内置了全局 fetch API,与浏览器端一致。

// GET 请求
interface User {
    id: number;
    name: string;
    email: string;
}

async function getUser(id: number): Promise<User> {
    const res = await fetch(`https://api.example.com/users/${id}`);
    if (!res.ok) throw new Error(`HTTP ${res.status}: ${res.statusText}`);
    return (await res.json()) as User;
}

// POST 请求
async function createUser(name: string, email: string): Promise<User> {
    const res = await fetch("https://api.example.com/users", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ name, email }),
    });
    if (!res.ok) throw new Error(`创建失败: ${res.status}`);
    return (await res.json()) as User;
}

如果需要拦截器、超时控制、自动重试等高级功能,可以使用 axios

npm install axios

5. WebSocket

WebSocket 提供全双工通信,适合聊天、实时通知等场景。Node.js 中最常用的库是 ws

npm install ws
npm install -D @types/ws
import { WebSocketServer, WebSocket } from "ws";

const wss = new WebSocketServer({ port: 8080 });
const clients = new Set<WebSocket>();

wss.on("connection", (ws) => {
    clients.add(ws);
    console.log(`新连接,当前 ${clients.size} 个客户端`);

    ws.on("message", (data) => {
        const msg = data.toString();
        console.log("收到:", msg);
        // 广播给所有客户端
        for (const client of clients) {
            if (client !== ws && client.readyState === WebSocket.OPEN) {
                client.send(msg);
            }
        }
    });

    ws.on("close", () => {
        clients.delete(ws);
    });
});

console.log("WebSocket 服务器已启动: ws://localhost:8080");

📝 本章要点

原生 http 适合学习

实际项目推荐 Express 或 Fastify

Express = 路由 + 中间件

理解中间件链是掌握 Express 的关键

fetch 是标准 HTTP 客户端

Node 18+ 内置,复杂场景选 axios

WebSocket 用于实时通信

ws 库轻量高效,适合服务端双向推送