Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/393.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 在Node.js中创建ID到套接字的映射,反之亦然_Javascript_Sockets_Node.js_Network Programming - Fatal编程技术网

Javascript 在Node.js中创建ID到套接字的映射,反之亦然

Javascript 在Node.js中创建ID到套接字的映射,反之亦然,javascript,sockets,node.js,network-programming,Javascript,Sockets,Node.js,Network Programming,我正在尝试管理一组套接字连接。我的应用程序基本上是一个http服务器,它接收帖子并将其传递到套接字。客户端打开套接字连接时,会发送一条带有id的connect消息: {"m":"connect","id":"1"} 然后,应用程序将此id和套接字保存在id2socket和socket2id映射中。断开连接时,将从映射中删除套接字/id对 post还将包含一个id,该id指示post数据应发送到具有该id的套接字 这太好了,对于一个开放式插座来说效果很好。但是,当我打开多个插座,然后关闭一个插座

我正在尝试管理一组套接字连接。我的应用程序基本上是一个http服务器,它接收帖子并将其传递到套接字。客户端打开套接字连接时,会发送一条带有id的connect消息:

{"m":"connect","id":"1"}
然后,应用程序将此id和套接字保存在id2socket和socket2id映射中。断开连接时,将从映射中删除套接字/id对

post还将包含一个id,该id指示post数据应发送到具有该id的套接字

这太好了,对于一个开放式插座来说效果很好。但是,当我打开多个插座,然后关闭一个插座时,断开连接会清除地图上的所有内容。我认为我对节点中套接字的理解是不完整的——回调中是否只使用了一个套接字对象?有没有更好的方法来管理我的开放式套接字连接和ID

启动服务器:

>>node server.js 
TCP server listening on 127.0.0.1:5280
HTTP server listening on 127.0.0.1:9002
远程登录:

>>telnet localhost 5280
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
{"m":"connect","id":"123"}
{"m":"connect","id":"123","success":"true"}
连接后的服务器:

>>Connection from 127.0.0.1:57572
received data: {"m":"connect","id":"123"}

id: 1
m: connect
associating uid 1 with socket [object Object]
做一个帖子:

python post.py {"foo":"bar"}
所以,对于几个打开的套接字来说,这很好(只要一个设备的id是123,服务器现在就已经硬连线了)。但是,一旦关闭一个连接,所有套接字连接都将从映射中删除

这是我的密码:

要发布的python脚本:

import sys
import json
import httplib, urllib, urllib2

values = json.loads('{"foo":"bar"}')
headers = {"Content-type": "application/json"}

conn = httplib.HTTPConnection('127.0.0.1', 9002)
headers = {"Content-type": "application/json"}
conn.request("POST", "", json.dumps(values), headers)
response = conn.getresponse()

print "response.status: "+response.status
print "response.reason: "+response.reason
print "response.read: "+response.read()
conn.close()
节点服务器(http和tcp),硬连接到post上向设备“123”发送数据:

var net = require('net'); // tcp-server
var http = require("http"); // http-server
var qs = require('querystring'); // http-post

// Map of sockets to devices
var id2socket = new Object;
var socket2id = new Object;

// Setup a tcp server
var server_plug = net.createServer(function(socket) {

    // Event handlers
    socket.addListener("connect", function(conn) {
        console.log("Connection from " + socket.remoteAddress + ":" + socket.remotePort );  
    });

    socket.addListener("data", function(data) {
        console.log("received data: " + data);
        try {
            request = JSON.parse(data);

            response = request;
            if(request.m !== undefined && request['id'] !== undefined){ // hack on 'id', id is js obj property
                console.log("id: "+request['id']);
                console.log("m: "+request.m);
                if(request.m == 'connect'){
                    console.log("associating uid " + request['id'] + " with socket " + socket);
                    id2socket[request['id']] = socket;
                    socket2id[socket] = request['id'];
                    response.success = 'true';
                } else {
                    response.success = 'true';
                }
            }
            socket.write(JSON.stringify(response));
        } catch (SyntaxError) {
            console.log('Invalid JSON:' + data);
            socket.write('{"success":"false","response":"invalid JSON"}');
        }
    });

    socket.on('end', function() {
        id = socket2id[socket]
        console.log("socket disconnect by id " + id);

        // wipe out the stored info
        console.log("removing from map socket:"+socket+" id:"+id);
        delete id2socket[id];
        delete socket2id[socket];
    });

    socket.on('timeout', function() {
        console.log('socket timeout');
    });

});

// Setup http server
var server_http = http.createServer(
    // Function to handle http:post requests, need two parts to it
    // http://jnjnjn.com/113/node-js-for-noobs-grabbing-post-content/
    function onRequest(request, response) {
        request.setEncoding("utf8");

        request.addListener("data", function(chunk) {
            request.content += chunk;
        });

        request.addListener("end", function() {
            console.log("post received!");
            //console.log("Request received: "+request.content);


            if (request.method == 'POST') {
                //var json = qs.parse(request.content);
                //console.log("Post: "+json);

                // HACK TO TEST STUFF:
                // send a message to one of the open sockets
                try {
                    var socket = id2socket['123']; //hardwired 
                    socket.write('{"m":"post"}');
                } catch (Error) {
                    console.log("Cannot find socket with id "+'123');
                }
            }
        });
    }
);


// Fire up the servers
var HOST = '127.0.0.1';
var PORT = 5280;
var PORT2 = 9002;

server_plug.listen(PORT, HOST);
console.log("TCP server listening on "+HOST+":"+PORT);

server_http.listen(PORT2);
console.log("HTTP server listening on "+HOST+":"+PORT2);

对象仅将字符串作为其属性的键。如日志所示,套接字对象被转换为字符串
“[object object]”
。因此,套接字#2覆盖对象中套接字#1的id,因为所有套接字都转换为相同的字符串键。因此,对象中始终只有一个属性,因为所有套接字都指向同一个键。当您尝试删除套接字#2的id时,单个属性将被删除,对象为空

当用作键时,您似乎希望每个单独的套接字都有一个自定义属性。您可以为此使用
WeakMap
s
WeakMap
s确实允许对象作为键(与仅字符串键相反),但由于它们相对较新,目前可能包含bug

(请注意,
id2socket
map可以只是一个普通对象,因为数字可以很好地转换为字符串,并且每个数字都有自己独特的字符串表示*)

使用
WeakMap
s如下:

var socket2id = new WeakMap; // as if you were doing: var socket2id = {};
socket2id.set(socket, id);   // as if you were doing: socket2id[socket] = id;
socket2id.get(socket);       // as if you were doing: socket2id[socket];
socket2id.delete(socket);    // as if you were doing: delete socket2id[socket];

确保使用
节点--harmony
(>=0.7)或
节点--harmony\u weakmaps
(对象仅将字符串作为其属性的键。如日志所示,套接字对象将转换为字符串
“[object object object]”
。因此,套接字2将覆盖对象中套接字1的id,因为所有套接字都转换为同一个字符串键。因此,对象中始终只有一个属性,因为所有套接字都归结为同一个键。当您尝试删除套接字2的id时,单个属性将被删除,对象为空。

当用作键时,您似乎希望每个单独的套接字都有一个自定义属性。为此,您可以使用
WeakMap
s。
WeakMap
s确实允许对象作为键(而不是仅字符串键),但由于它们相对较新,目前可能包含错误

(请注意,
id2socket
map可以只是一个普通对象,因为数字可以很好地转换为字符串,并且每个数字都有自己独特的字符串表示*)

使用
WeakMap
s如下:

var socket2id = new WeakMap; // as if you were doing: var socket2id = {};
socket2id.set(socket, id);   // as if you were doing: socket2id[socket] = id;
socket2id.get(socket);       // as if you were doing: socket2id[socket];
socket2id.delete(socket);    // as if you were doing: delete socket2id[socket];
确保使用
节点--harmony
(>=0.7)或
节点--harmony\u weakmap
(