多个套接字覆盖自身

Posted

技术标签:

【中文标题】多个套接字覆盖自身【英文标题】:Multiple sockets override itself 【发布时间】:2018-08-11 16:39:54 【问题描述】:

我的代码

我想与 telnet 控制台建立多重连接。这个项目是针对 Teamspeak 的,Teamspeak 只是通过 telnet 进行通信。我有一个对象,它使用 net lib 创建一个 telnet 连接作为套接字。如果我们只有一个实例来连接所有工作正常,我通过 telnet 连接获取服务器列表。但如果我有两个实例,他会说invalid loginname or password。登录信息正确,他也尝试连接到一台服务器。

我的班级:

/*
    Teamspeak query client class
    @instance: Instance object of the teamspeak query client
*/
function TeamspeakQueryClient(instance) 
    events.EventEmitter.call(this);

    var $this = this,
        socket = net.connect(instance.port, instance.ip),
        reader = null,
        skipLines = -2,
        queue = [ ],
        executing = null,
        server = null;

    this.Type = 'Unknown';
    this.Id = null;
    this.Connected = false;
    this.Banned = false;

    /*
        Socket settings
    */
    socket.setKeepAlive(true, 60000);

    /*
        Socket connect to the teamspeak instance
    */
    socket.on("connect", function() 
        reader = LineInputStream(socket);
        reader.on("line", function(line) 
            var s = line.trim();
            console.log(line);

            // Skipp the first lines
            if(skipLines < 0)
                if(line === 'TS3') 
                    this.Type = 'Teamspeak';
                ;

                skipLines++;

                if(skipLines === 0) 
                    checkQueue();

                    if(server === null) 
                        $this.SendCommand("login", client_login_name: instance.client, client_login_password: instance.password, function(err, response, rawResponse) 
                            console.log(err);
                            if(err === null) 
                                if(err.id === 3329) 
                                    $this.Banned = true;
                                ;

                                $this.CloseSocket();
                             else 
                                $this.SendCommand("serverlist", null, function(err, response, rawResponse)
                                    console.log(response);
                                    if(response[0] === undefined) 
                                        console.log('1 server');
                                     else 
                                        console.log('mehrere server');
                                    ;
                                    //console.log(rawResponse);
                                    /*cl.send("clientlist", function(err, response, rawResponse)
                                        console.log(util.inspect(response));
                                    );*/
                                );
                            ;
                        );
                     else 
                        console.log(server);   
                    ;
                ;

                return;
            ;

            // Parse server request
            var response = undefined;
            if(s.indexOf("error") === 0)
                response = parseResponse(s.substr("error ".length).trim());
                executing.error = response;
                if(executing.error.id === 0) delete executing.error;
                if(executing.cb) executing.cb.call(executing, executing.error, executing.response,
                executing.rawResponse);
                executing = null;
                checkQueue();
             else if(s.indexOf("notify") === 0)
                s = s.substr("notify".length);
                response = parseResponse(s);
                $this.emit(s.substr(0, s.indexOf(" ")), response);
             else if(executing) 
                response = parseResponse(s); 
                executing.rawResponse = s;
                executing.response = response;
            ;
        );

        $this.emit("connect");
    );

    /*
        Socket error
    */
    socket.on("error", function(err)
        log.LogLine(1, 'TeamspeakQueryClient: We got a error');
        log.LogLine(1, 'Message: '+err);
        $this.emit("error", err);
    );

    /*
        Socket close
    */
    socket.on("close", function()
        log.LogLine(3, 'TeamspeakQueryClient: Socket from '+instance.alias+' closeing...');
        $this.emit("close", queue);
    );

    /*
        Function to send a custom command to the telnet console
    */
    TeamspeakQueryClient.prototype.SendCommand = function SendCommand() 
        var args = Array.prototype.slice.call(arguments);
        //console.log(args);
        var options = [], params = ;
        var callback = undefined;
        var cmd = args.shift();
        args.forEach(function(v)
            if(util.isArray(v))
                options = v;
             else if(typeof v === "function")
                callback = v;
             else 
                params = v;
            
        );
        var tosend = tsescape(cmd);
        options.forEach(function(v)
            tosend += " -" + tsescape(v);
        );
        for(var k in params)
            var v = params[k];
            if(util.isArray(v)) // Multiple values for the same key - concatenate all
                var doptions = v.map(function(val)
                    return tsescape(k) + "=" + tsescape(val); 
                );
                tosend += " " + doptions.join("|");
             else 
                tosend += " " + tsescape(k.toString()) + "=" + tsescape(v.toString());
            
        
        queue.push(cmd: cmd, options: options, parameters: params, text: tosend, cb: callback);
        if(skipLines === 0) checkQueue();
    ;

    /*
        Function to close the socket
    */
    TeamspeakQueryClient.prototype.CloseSocket = function CloseSocket() 
        socket.destroy();
        $this.emit("close");
    ;

    /*
        Function to parse a string to a object
        @s: String of the object that will be parsed
        @return: Object of the parsed string
    */
    function parseResponse(s)
        var response = [];
        var records = s.split("|");

        response = records.map(function(k)
            var args = k.split(" ");
            var thisrec =  ;
            args.forEach(function(v) 
                if(v.indexOf("=") > -1) 
                    var key = tsunescape(v.substr(0, v.indexOf("=")));
                    var value = tsunescape(v.substr(v.indexOf("=")+1));
                    if(parseInt(value, 10) == value) value = parseInt(value, 10);
                    thisrec[key] = value;
                 else 
                    thisrec[v] = "";
                ;
            );
            return thisrec;
        );

        if(response.length === 0) 
            response = null;
         else if(response.length === 1) 
            response = response.shift();
        ;

        return response;
    ;

    /*
        Function to write commands into the socket
    */
    function checkQueue() 
        if(!executing && queue.length >= 1)
            executing = queue.shift();
            socket.write(executing.text + "\n");
        ;
    ;

    /*
        Function to escape a telnet string
        @s: String that want to be escaped
        @return: The escaped string
    */
    function tsescape(s) 
        return s
            .replace(/\\/g, "\\\\")
            .replace(/\//g, "\\/")
            .replace(/\|/g, "\\p")
            .replace(/\n/g, "\\n")
            .replace(/\r/g, "\\r")
            .replace(/\t/g, "\\t")
            .replace(/\v/g, "\\v")
            .replace(/\f/g, "\\f")
            .replace(/ /g,  "\\s");
    ;

    /*
        Function to unescape a telnet string
        @s: String that want to be unescaped
        @return: The unescaped string
    */
    function tsunescape(s) 
        return s
            .replace(/\\s/g,  " ")
            .replace(/\\p/g,  "|")
            .replace(/\\n/g,  "\n")
            .replace(/\\f/g,  "\f")
            .replace(/\\r/g,  "\r")
            .replace(/\\t/g,  "\t")
            .replace(/\\v/g,  "\v")
            .replace(/\\\//g, "\/")
            .replace(/\\\\/g, "\\");
    ;
;

util.inherits(TeamspeakQueryClient, events.EventEmitter);

我如何打开课程

如果我调用示例一一切正常,但示例二有描述的错误。

示例 1:

 test1 = new TeamspeakQueryClient(
    "alias": "First-Coder Testinsance",
    "ip": "first-coder.de",
    "port": 10011,
    "client": "serveradmin",
    "password": "SECURE"
);

示例 2:

 test1 = new TeamspeakQueryClient(
    "alias": "First Insance",
    "ip": "HIDDEN",
    "port": HIDDEN,
    "client": "serveradmin",
    "password": "SECURE"
);
test2 = new TeamspeakQueryClient(
    "alias": "Second Instance",
    "ip": "HIDDEN",
    "port": HIDDEN,
    "client": "serveradmin",
    "password": "SECURE"
);

截图

Picture of the error in the console

【问题讨论】:

尝试用一个实例运行 2 个节点进程,而不是在一个进程中运行 2 个实例。检查问题是来自您的代码还是人才阻止了用户 她自己?怎么看出是女的?我总是虽然它是男性:| @Red: 我知道我的英语不是最好的 :D @AmitWagner:如果我尝试使用它工作的每个实例来连接进程。但是一个实例每次都运行良好。我没有 3 个实例... 在您的第一个和第二个示例中,您有不同的 cardinals 。你能试着把工作的红衣主教放2个实例吗 【参考方案1】:

根据您的错误,您的第二个实例未发送正确的登录信息:

错误 id=520 msg=invalid\sloginname\sor\spassword

显示的其他错误是由于您的代码未正确处理错误。 例如:

socket.on("connect", function() 
...
    if(err === null) 
        if(err.id === 3329) 

如果err === null,为什么err 会有一个元素id? 这很可能是代码错误,您实际上是指err !== null

$this.SendCommand("serverlist", null, function(err, response, rawResponse)
    console.log(response);
    if(response[0] === undefined) 

此错误触发是因为(以上)先前的错误未被捕获。

此时,客户端未登录(授权)。

所以当serverlist 命令被发送时,它会触发另一个错误。

这个额外的错误也没有被处理,而是立即使用response

【讨论】:

以上是关于多个套接字覆盖自身的主要内容,如果未能解决你的问题,请参考以下文章

Python套接字实现

监听多个套接字:选择与多线程

套接字 IO:如何定义断开连接的套接字 id(当多个选项卡时)?

每个单独的 TCP 套接字的多个挂起读取或多个挂起写入的性能优势?

Java 可以并行运行同一个套接字的多个实例吗?

多个套接字可以与 UDP 的同一端口相关联吗?