VScode原始碼分析:查詢服務可用的埠
阿新 • • 發佈:2018-12-09
基本資訊:
分支: master;
commitID: 3c4e9323;
檔案路徑: src/vs/base/node/ports.ts
基本思路:
1、查詢方法返回一個Promise(結果為resolve)
2、與127.0.0.1逐個埠進行Socket連線:
-
connect:埠已經被佔用,繼續查詢;
-
error:error.code = ECONNREFUSED埠可用,否則埠被佔用且不能連線;
原始碼:
/** * Given a start point and a max number of retries, will find a port that * is openable. Will return 0 in case no free port can be found. */ export function findFreePort(startPort: number, giveUpAfter: number, timeout: number): Thenable<number> { let done = false; return new Promise(resolve => { const timeoutHandle = setTimeout(() => { //超時後退出並返回未找到 if (!done) { done = true; return resolve(0); } }, timeout); doFindFreePort(startPort, giveUpAfter, (port) => { //逐個查詢埠 if (!done) { done = true; clearTimeout(timeoutHandle); return resolve(port); } }); }); }
function doFindFreePort(startPort: number, giveUpAfter: number, clb: (port: number) => void): void { if (giveUpAfter === 0) { return clb(0); } const client = new net.Socket(); // If we can connect to the port it means the port is already taken so we continue searching client.once('connect', () => { dispose(client); //一旦連線或error都要關閉 return doFindFreePort(startPort + 1, giveUpAfter - 1, clb); }); client.once('data', () => { // this listener is required since node.js 8.x }); client.once('error', (err: Error & { code?: string }) => { dispose(client); // If we receive any non ECONNREFUSED error, it means the port is used but we cannot connect if (err.code !== 'ECONNREFUSED') { return doFindFreePort(startPort + 1, giveUpAfter - 1, clb); } // Otherwise it means the port is free to use! return clb(startPort); }); client.connect(startPort, '127.0.0.1'); }
function dispose(socket: net.Socket): void { try { socket.removeAllListeners('connect'); //移除connect監聽 socket.removeAllListeners('error'); //移除error監聽 socket.end(); //半關閉 socket,服務端仍可以傳送資料 socket.destroy(); //確保在該 socket 上不再有 I/O 活動。僅在出現錯誤的時候才需要(如解析錯誤等) socket.unref(); //如果活躍的 socket 是事件系統中僅存的 socket,則呼叫 unref 將會允許程式退出 } catch (error) { console.error(error); // otherwise this error would get lost in the callback chain } }
後記:
dispose中socket關閉的步驟還不是很清楚,相關連線