上一章介紹瞭如何解析 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 協議就被咱們實現了!對象