简单了解 node net 模块
文章简单记录了对net 模块的理解分析。
Node.js 的 Net模块用于创建基于流的 TCP 或 IPC 的服务器(net.createServer())与客户端(net.createConnection())。
Node.js 的 Net模块是基于TCP协议的socket网路编程模块。
主要的两个部分
先写个小例子:
TCP服务端:
let net = require(‘net‘) let server = net.createServer({}, socket => { // socket 是一个双工流 console.log(‘client connected‘) socket.on(‘data‘, data => { console.log(data.toString()) socket.write(‘server: hello server‘) }) // 服务器收到客户端发出的关闭请求时,会触发end事件 socket.on(‘end‘, () => { console.log(‘client disconnected‘) }) socket.on(‘close‘, () => { console.log(‘client closed‘) }) }) server.listen(8080, () => { console.log(‘server start‘); })
TCP客户端:
let net = require(‘net‘) // new net.Socket() 返回的是一个双工流 let client = new net.Socket() client.connect(8080, ‘localhost‘, () => { console.log(‘connected server‘) client.write(‘client: hello server‘); }) client.on(‘data‘, function (data) { console.log(data.toString()) }); setTimeout(()=>{ client.end() },5000)
上面流程调试代码画个简图:
TCP服务是一connection 为单位进行服务的。
createServer就是一个语法糖,帮助new生成server对象,
server 对象继承了EventEmitter对象 。
_handle属性值最终由c++部分的TCP、Pipe类创建的。
function Server(options, connectionListener) { if (!(this instanceof Server)) return new Server(options, connectionListener); // 调用 EventEmitter 获得属性 EventEmitter.call(this); // 订阅connection 事件 this.on(‘connection‘, connectionListener); // 统计连接数量 this._connections = 0; this[async_id_symbol] = -1;
// 会挂载TCP对象 this._handle = null; this._usingWorkers = false; this._workers = []; this._unref = false; this.allowHalfOpen = options.allowHalfOpen || false; this.pauseOnConnect = !!options.pauseOnConnect; }
每当有客户端连接时,就会调用callback函数onconnection函数,创建socket,然后在
self.emit(‘connection‘, socket)
所以server 对象更多的是对socket连接的管理。
function onconnection(err, clientHandle) { const handle = this; const self = handle[owner_symbol]; // 超出最大链接数 不让客户端连接 if (self.maxConnections && self._connections >= self.maxConnections) { clientHandle.close(); return; } const socket = new Socket({ handle: clientHandle, allowHalfOpen: self.allowHalfOpen, pauseOnCreate: self.pauseOnConnect, readable: true, writable: true }); // 连接数增加 self._connections++; socket.server = self; socket._server = self; DTRACE_NET_SERVER_CONNECTION(socket); // 发布 connection self.emit(‘connection‘, socket); }
onconnection执行的目的是对应用程序构的连接造出一个socket的对象,并且基于此对象完成面向connection的数据流读取操作。
socket(通过 socket=new Socket() ) 是个双工流源码截取如下:
socket._handle上的对象是由C++中的Pipe、TCP实现,大概截取代码如下
//<------Socket函数-----> this._handle = createHandle(fd, false); //<------createHandle函数-----> function createHandle(fd, is_server) { validateInt32(fd, ‘fd‘, 0); const type = guessHandleType(fd); if (type === ‘PIPE‘) { return new Pipe( is_server ? PipeConstants.SERVER : PipeConstants.SOCKET ); } if (type === ‘TCP‘) { return new TCP( is_server ? TCPConstants.SERVER : TCPConstants.SOCKET ); } throw new ERR_INVALID_FD_TYPE(type); }
由c++部分的TCP、Pipe类创建由internalBinding(‘tcp_wrap‘)导出的TCP对象,如下:
Node.js 的 Net模块其实是对 c++部分的TCP、Pipe类创建的socket 进行了抽象封装。
所以socke实例有Writable,Readable,和TCP的相关功能函数。
TCP服务是一connection 为单位进行服务的。
要理解net模块或者net模块的API 除了多看文档,还可以看看TCP协议,链接建立握手,慢启动拥塞控制,Nagle算法解决的问题等等。
文章简单记录了对net 模块的理解分析。例子用词比较粗糙,理解不准确之处,还请教正。
原文:https://www.cnblogs.com/luoxiaoer/p/11894401.html