创建http.Server实例,端口占用就换个端口

/**
 * Created by Sorrow.X on 2017/10/25.
 */

const http = require('http');
const url  = require('url');
const net = require('net');

// 单例
let httpServer = (function() {

    let port = 8888;
    let server = null;
    let serverStartedCb = null;
    let noop = function() {};

    // 初始化http服务器
    let initServer = function({serverStarted}) {
        serverStartedCb = serverStarted || noop;
        startServer(increPort());
    };

    // 关闭服务器
    let closeServer = function() {
        if (server) {
            server.close();
            server = null;
        };
    };

    // 端口增加
    function increPort() {
        return ++port;
    };

    // 格式化url
    function format(str) {
        let obj = {};
        str = str.substr(str.indexOf('?') + 1);
        let arr = str.split('&');
        arr.forEach(function(item) {
            let a = item.split('=');
            obj[a[0]] = a[1];
        });
        return obj;
    };

    // 启动服务器
    function _server(port) {

        server = new http.Server();

        server.on('request',(req, res)=>{
            let content = {
                Code: -1,
                Body: {
                    message: 'request url error'
                }
            };
            if (req.url.indexOf('ball/queryUrl') > 0) {
                let obj = format(req.url);
                if (obj.type == '1') {
                    content.Code = 0;
                    content.Body = {
                        message: 'hi'
                    };
                };
            };
            //设置应答头信息
            res.writeHead(200,{'Content-Type':'text/plain'});
            res.write(JSON.stringify(content));
            res.end();
        });

        server.on('listening', () => {
            console.log("server listening, 端口号和url为: ", `localhost:${port}`);
            serverStartedCb(null);
        });

        server.on('connection', () => {
            console.log("server connection...");
        });

        server.on('close', () => {
            console.log('server close...');
        });

        server.on('error', (err) => {
            server.close();
            server = null;
            serverStartedCb(new Error(err));
            console.log('server error: ', err);
        });

        server.listen(port);
    };

    // 检测port是否被占用
    function probe(port, callback) {

        let server = net.createServer().listen(port);

        let calledOnce = false;

        let timeoutRef = setTimeout(function () {
            calledOnce = true;
            callback(false, port);
        }, 2000)

        timeoutRef.unref(); // 取消定时器

        let connected = false;

        server.on('listening', function() {
            clearTimeout(timeoutRef);

            if (server)
                server.close();

            if (!calledOnce) {
                calledOnce = true;
                callback(true, port); // true 表示未被占用
            };
        });

        server.on('error', function(err) {
            clearTimeout(timeoutRef);

            let result = true;
            if (err.code === 'EADDRINUSE')
                result = false; // 占用

            if (!calledOnce) {
                calledOnce = true;
                callback(result, port); // false 表示占用
            };
        });
    };

    function startServer(port){
        probe(port, function(bool, port) { // 端口被占用: bool 返回false; port:传入的端口号
            if (bool === true) { // 端口号未被占用
                _server(port);
            } else { // 已占用
                closeServer();
                _server(increPort());
            };
        });
    };

    let single;
    return function() {
        return single ? single : (single = {initServer, closeServer});
    };
}());

// module.exports = httpServer();

// test
var ballServer = httpServer();
var ballServer2 = httpServer();

console.log(ballServer === ballServer2); // 测试是否同一个对象

ballServer.initServer({
    serverStarted: function(err) {
        if (!err) {
            console.log('服务已启动: ');
        };
    }
});
// ballServer.closeServer();

 

posted @ 2017-10-25 17:29  Sorrow.X  阅读(2000)  评论(0编辑  收藏  举报