上一章介绍了如何解析 HTTP 请求报文,这一章咱们来说解如何进行报文的收发和 TCP 链接的创建。git
TCP 是一条全双工通讯通道,咱们能够经过使用 Node 的 net
模块来建立一个 TCP 进程,监听来自客户端的请求,使用方法以下:github
net.createServer((socket) => { socket.on('data', (data: Buffer) => { // ... 处理接收的客户端信息 }); socket.on('error', error => { // ... 处理出错信息 }); });
在 data
事件中所接收到的数据属于字节流数据(Buffer 对象),咱们须要使用 Buffer
对象自带的 toString
方法来进行对字节流的解析,将其转化为 utf-8
格式的字符。socket
而后将转化后的字符串交由咱们的 HttpParser
处理,而后将序列化的请求对象挂载在 http.createServer((req, res) => {})
中的 req
上,同时能够经过 res.end(message)
进行报文响应。函数
咱们将上述步骤解析一下可得知,咱们还须要两个类,一个用来承载 Request 信息,一个用于处理响应结果的 Response,那咱们如今来新建这两个类:this
// 用于处理请求信息 import HttpParser, { HttpMessage } from "./HttpParser"; class IncomingMessage { private httpParser: HttpParser; public httpMessage: HttpMessage; constructor(message: string) { this.httpParser = new HttpParser(message); this.httpMessage = this.httpParser.httpMessage; } } export default IncomingMessage;
// 用于响应处理结果 import * as net from 'net'; // ResponseFormatter 就是反序列化 JSON 数据的类,可从源码仓库查看 import ResponseFormatter from './ResponseFormatter'; class ServerResponse { private socket: net.Socket; private resFormatter: ResponseFormatter; constructor(socket: net.Socket) { this.socket = socket; this.resFormatter = new ResponseFormatter(); } public setHeader(key: string, val: string) { this.resFormatter.setHeader(key, val); } public end(status: number, body: string) { const resFormatter = this.resFormatter; resFormatter.setStatus(status); resFormatter.setBody(body); // 下面三步就是向客户端发送 TCP 字节流数据 this.socket.write(resFormatter.format()); this.socket.pipe(this.socket); this.socket.end(); } } export default ServerResponse;
最后咱们在咱们的事件监听中,加入这两个处理对象:code
socket.on('data', (data: Buffer) => { // ... 处理接收的客户端信息 const message = data.toString('utf-8'); // 解码字节流数据 this.request = new IncomingMessage(message); // 封装 request 对象 this.response = new ServerResponse(socket); // 封装 response 对象 this.handler(this.request, this.response); // 将两个对象做为参数传入回调函数 });
如今咱们只须要正确的将回调函数添加到 HTTP
对象中便可,咱们最后的 HTTP
类的实现以下:orm
import * as net from 'net'; import * as EventEmitter from 'events'; import IncomingMessage from "./IncomingMessage"; import ServerResponse from "./ServerResponse"; type Handler = (request: IncomingMessage, response: ServerResponse) => void; class HTTP extends EventEmitter{ handler: Handler; request: IncomingMessage; response: ServerResponse; server: net.Server; socket: net.Socket; constructor(handler: Handler) { super(); this.handler = handler; this.createServer(); } private createServer(): void { this.server = net.createServer((socket) => { socket.on('data', (data: Buffer) => { const message = data.toString('utf-8'); this.request = new IncomingMessage(message); this.response = new ServerResponse(socket) this.handler(this.request, this.response); }); socket.on('error', error => { this.emit('error', error) }); }); } public listen(port: number, cb: any = () => { }): void { this.server.listen(port, cb); this.server.on('error', error => this.emit('error', error)); } } const createServer = (handler: Handler) => { return new HTTP(handler) } export default { createServer }
完成最后的 HTTP
类后,咱们就能够经过第一章的方法去建立一个 HTTP 服务端了,而且能够处理请求信息,将请求信息如数返回给客户端。server
至此,一个 HTTP 协议就被咱们实现了!对象