HTTP、WebSocket、TCP详解 | 从零基础到精通 | 包含协议、实现和优化
网络编程是指通过网络进行数据通信的编程。它涉及多台计算机之间通过网络进行数据交换。
客户端 -> 服务器: SYN (seq=x)
服务器 -> 客户端: SYN-ACK (seq=y, ack=x+1)
客户端 -> 服务器: ACK (seq=x+1, ack=y+1)
连接建立,开始数据传输TCP:
- 建立连接(三次握手)
- 可靠传输
- 有序性
- 流量控制
- 适用:文件传输、邮件、Web
UDP:
- 无连接
- 快速传输
- 不保证顺序
- 适用:视频、音频、实时游戏GET /api/users HTTP/1.1
Host: example.com
User-Agent: Mozilla/5.0
Accept: application/json
Authorization: Bearer token123
请求行:GET /api/users HTTP/1.1
请求头:Host, User-Agent, Accept, Authorization
请求体:(GET请求通常没有请求体)HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 123
Cache-Control: max-age=3600
{
"id": 1,
"name": "Alice"
}
状态行:HTTP/1.1 200 OK
响应头:Content-Type, Content-Length, Cache-Control
响应体:JSON数据1. 客户端发送请求到服务器
2. 服务器返回证书和公钥
3. 客户端验证证书
4. 客户端生成对称密钥,用公钥加密
5. 服务器用私钥解密,获得对称密钥
6. 双方使用对称密钥加密通信# 生成自签名证书
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365
# 在Node.js中使用HTTPS
const https = require('https');
const fs = require('fs');
const options = {
key: fs.readFileSync('key.pem'),
cert: fs.readFileSync('cert.pem')
};
https.createServer(options, (req, res) => {
res.writeHead(200);
res.end('Hello HTTPS!');
}).listen(443);客户端请求:
GET /chat HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13
服务器响应:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=// 服务器
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
wss.on('connection', (ws) => {
ws.on('message', (message) => {
// 广播给所有客户端
wss.clients.forEach((client) => {
if (client.readyState === WebSocket.OPEN) {
client.send(message);
}
});
});
});
// 客户端
const ws = new WebSocket('ws://localhost:8080');
ws.onmessage = (event) => {
console.log('Message:', event.data);
};1. 用户输入 example.com
2. 浏览器查询本地DNS缓存
3. 如果没有,查询递归解析器
4. 递归解析器查询根域名服务器
5. 根服务器返回顶级域名服务器地址
6. 查询顶级域名服务器
7. 返回权威域名服务器地址
8. 查询权威域名服务器
9. 返回IP地址
10. 浏览器缓存结果并建立连接// Node.js DNS查询
const dns = require('dns');
dns.resolve4('example.com', (err, addresses) => {
if (err) throw err;
console.log('IPv4 addresses:', addresses);
});
dns.resolveMx('example.com', (err, addresses) => {
if (err) throw err;
console.log('MX records:', addresses);
});const net = require('net');
const server = net.createServer((socket) => {
console.log('Client connected');
socket.write('Welcome to the server\n');
socket.on('data', (data) => {
console.log('Received:', data.toString());
socket.write('Echo: ' + data);
});
socket.on('end', () => {
console.log('Client disconnected');
});
socket.on('error', (err) => {
console.error('Error:', err);
});
});
server.listen(3000, () => {
console.log('Server listening on port 3000');
});const net = require('net');
const client = net.createConnection(3000, 'localhost');
client.on('connect', () => {
console.log('Connected to server');
client.write('Hello Server\n');
});
client.on('data', (data) => {
console.log('Received:', data.toString());
});
client.on('end', () => {
console.log('Disconnected from server');
});
client.on('error', (err) => {
console.error('Error:', err);
});const dgram = require('dgram');
// 服务器
const server = dgram.createSocket('udp4');
server.on('message', (msg, rinfo) => {
console.log('Received:', msg.toString());
server.send('Echo: ' + msg, rinfo.port, rinfo.address);
});
server.bind(3000);
// 客户端
const client = dgram.createSocket('udp4');
client.send('Hello', 3000, 'localhost', (err) => {
if (err) throw err;
console.log('Message sent');
});
client.on('message', (msg) => {
console.log('Received:', msg.toString());
client.close();
});// 浏览器缓存
Cache-Control: public, max-age=3600
// ETag条件请求
If-None-Match: "33a64df551425fcc55e4d42a148795d9f25f89d4"
// Last-Modified
If-Modified-Since: Wed, 21 Oct 2023 07:28:00 GMT
// CDN缓存
Cache-Control: public, max-age=86400const express = require('express');
const http = require('http');
const WebSocket = require('ws');
const app = express();
const server = http.createServer(app);
const wss = new WebSocket.Server({ server });
const clients = new Map();
wss.on('connection', (ws) => {
const clientId = Date.now().toString();
clients.set(clientId, ws);
console.log(`Client ${clientId} connected`);
// 广播用户列表
broadcastUserList();
ws.on('message', (message) => {
const data = JSON.parse(message);
// 广播消息给所有客户端
wss.clients.forEach((client) => {
if (client.readyState === WebSocket.OPEN) {
client.send(JSON.stringify({
type: 'message',
from: clientId,
text: data.text,
timestamp: new Date()
}));
}
});
});
ws.on('close', () => {
clients.delete(clientId);
console.log(`Client ${clientId} disconnected`);
broadcastUserList();
});
});
function broadcastUserList() {
const userList = Array.from(clients.keys());
wss.clients.forEach((client) => {
if (client.readyState === WebSocket.OPEN) {
client.send(JSON.stringify({
type: 'userlist',
users: userList
}));
}
});
}
server.listen(3000, () => {
console.log('Server listening on port 3000');
});通过这个项目,你学会了如何使用WebSocket构建实时通信应用。
现在你已经掌握了网络编程的核心知识。
网络编程是后端开发的基础。深入理解网络协议,能让你写出更高效、更安全的应用。