2012-02-10 47 views
0

我試圖管理一堆套接字連接。我的應用基本上是一個http服務器,它接收帖子並將它們傳遞給套接字。當客戶端打開一個套接字連接,它們發送連接消息的ID:在Node.js中創建ID到套接字的映射,反之亦然

{"m":"connect","id":"1"} 

的應用程序,然後保存該ID和插座在id2socket和socket2id地圖。斷開連接時,套接字/ ID對將從地圖中刪除。

一個帖子也會包含一個id,它表明發佈的數據應該被髮送到具有該id的套接字。

這很好,這對於單個打開的套接字可以很好地工作。但是,當我打開多個套接字,然後關閉一個套接字時,該斷開連接將擦除地圖上的所有內容。我認爲我對節點中的套接字的理解是不完整的 - 在回調中是否只有一個套接字對象?有沒有更好的方法來管理我的開放式套接字連接和ID?

啓動服務器:

>>node server.js 
TCP server listening on 127.0.0.1:5280 
HTTP server listening on 127.0.0.1:9002 

的telnet在:

連接後
>>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"} 

因此,這適用於多個開放套接字(只要1設備是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),硬連接將數據發送到設備 '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); 

回答

1

對象只將字符串作爲其屬性的鍵。如您的日誌所示,套接字對象被轉換爲字符串"[object Object]"。因此,套接字#2將覆蓋對象中套接字1的id,因爲所有套接字都轉換爲相同的字符串關鍵字。因此,對象中始終只有一個屬性,因爲所有套接字都歸入同一個關鍵字。當您嘗試刪除套接字2的ID時,單個屬性將被刪除並且該對象爲空。

你似乎想爲每個單獨的套接字使用一個自定義屬性作爲關鍵。您可以使用WeakMapWeakMap s確實允許對象作爲鍵(而不是字符串鍵),但由於它們相對較新,它們可能包含當前的錯誤。 (請注意,id2socket映射只能是一個普通對象,因爲數字轉換爲字符串就好了,每個數字都有自己的不同的字符串表示形式*。)

使用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]; 

確保用node --harmony運行(> = 0.7)或node --harmony_weakmaps(< = 0.6)。


*0-0有例外,但你不應該使用-0反正因爲0 === -0,所以很難在它們之間的不同。

相關問題