【问题标题】:node.js proxy server posts to http server and dies when http server is closednode.js 代理服务器发布到 http 服务器并在 http 服务器关闭时死亡
【发布时间】:2012-02-17 10:41:04
【问题描述】:

我正在通过代理服务器将数据从客户端套接字发送到 http 服务器。当我将这些数据从代理服务器发布到 http 时,一切正常,但如果我关闭 http 服务器,代理服务器就会死掉。

我认为 post.end() 函数会关闭请求,但显然不是?!我需要做一些回调魔法吗?

我在下面附上了我的控制台输出,但这里是对步骤的简要说明:

  1. 启动服务器:节点 --harmony_weakmaps server.js
  2. 启动api(http服务器):节点api.js
  3. 启动客户端(telnet localhost 5280)
  4. 客户端连接消息:{"m":"connect","id":"123"}
  5. 给 api 的客户端消息:{"m":"x","id":"123"}
  6. 杀死 api 进程 - 它爆炸了

控制台(服务器):

>>node --harmony_weakmaps server.js
Starting heartbeat
TCP server listening on 127.0.0.1:5280
HTTP server listening on 127.0.0.1:9002
Connection from 127.0.0.1:49356 id:undefined
received data: {"m":"connect","id":"123"}

id: 123
m: connect
associating uid 123 with socket [object Object]


Heartbeat Time: Tue Feb 14 2012 15:27:08 GMT-0800 (PST)
received data: {"m":"x","id":"123"}

id: 123
m: x
Invalid JSON:{"m":"x","id":"123"}

events.js:48
        throw arguments[1]; // Unhandled 'error' event
                       ^
Error: socket hang up
    at createHangUpError (http.js:1104:15)
    at Socket.onend (http.js:1181:27)
    at TCP.onread (net.js:369:26)

控制台(客户端,远程登录):

>>telnet localhost 5280
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
>>{"m":"connect","id":"123"}
{"m":"connect","id":"123","success":"true"}
{"m":"pulse"}
>>{"m":"x","id":"123"}
{"success":"false","response":"invalid JSON"}
Connection closed by foreign host.

控制台(api):

>>node api.js 
API (HTTP server) listening on 127.0.0.1:8081
Request received: m=x&id=123&success=true
id: 123
m: x
// Then I close it (^C)

server.js(将数据从套接字发送到 http 服务器的 tcp-ip 服务器):

// Launch Instructions
// node --harmony server.js

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

// Map of sockets to devices
var id2socket = new Object;
var socket2id = new WeakMap; // allows us to use object as key to hash

// HTTP:POST outbound function
// http://www.theroamingcoder.com/node/111
function postOut(dataToPost){
    var querystring = require('querystring');
    var http = require('http');

    var post_domain = 'localhost';
    var post_port = 8081;
    var post_path = '/';

    var post_data = querystring.stringify(dataToPost);

    var post_options = {
      host: post_domain,
      port: post_port,
      path: post_path,
      method: 'POST',
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded',
        'Content-Length': post_data.length
      }
    };

    var post_req = http.request(post_options, function(res) {
      res.setEncoding('utf8');
      res.on('data', function (chunk) {
        console.log('Response: ' + chunk);
      });
    });

    // write parameters to post body
    post_req.write(post_data);
    post_req.end();
    request.on("response", function (response) {
        console.log(response);
    });
}

function removeSocketFromMap(id,socket){
    console.log("removeSocketFromMap socket:"+socket+" id:"+id);
    delete id2socket[id];
    socket2id.delete(socket);
    //TODO: print map???
}

// 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 + " id:"+socket.id );   
        });

        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.set(socket, request['id']);
                        response.success = 'true';
                    } else {
                        response.success = 'true';

                        postOut(request)
                    }
                }
                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.get(socket);
            console.log("socket disconnect by id " + id);
            removeSocketFromMap(id,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.content = '';

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

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

            try {
                var json = JSON.parse(request.content);
                var id = json['id'];
                var m = json['m'];
                console.log("id: "+id);
                console.log("m: "+m);

                // TODO: refactor this into another function
                try {
                    var socket = id2socket[id];
                    socket.write('{"m":"post"}');
                } catch (Error) {
                    console.log("Cannot find socket with id "+id);
                }

            } catch(Error) {
                console.log("JSON parse error: "+Error)
            }
        });
    }
);

// Heartbeat function
console.log("Starting heartbeat");
var beat_period = 20;
setInterval(function() {
    console.log("Heartbeat Time: " + new Date());
    for(var id in id2socket) {
        var socket = id2socket[id];
        try {
            socket.write('{"m":"pulse"}');
        } catch(Error) {
            removeSocketFromMap(id,socket);
        }

    }
}, beat_period * 1000);




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

// accept tcp-ip connections
server_plug.listen(PORT, HOST);
console.log("TCP server listening on "+HOST+":"+PORT);

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

api.js(http 服务器):

var http = require("http"); // http-server
var querystring = require('querystring');

// 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.content = '';

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

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

            try {
                // Parse incoming JSON
                var json = querystring.parse(request.content);
                var id = json['id'];
                var m = json['m'];
                console.log("id: "+id);
                console.log("m: "+m);

            } catch(Error) {
                console.log("JSON parse error: "+Error)
            }
        });
    }
);


// Fire up the servers
var HOST = '127.0.0.1';
var PORT = 8081;

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

【问题讨论】:

    标签: http sockets node.js post


    【解决方案1】:

    我真傻,我没有跟上 node.js 中正确错误处理的速度。修复 postOut() 就行了:

    function postOut(dataToPost){
    
        var querystring = require('querystring');
        var http = require('http');
    
        var post_domain = 'localhost';
        var post_port = 8081;
        var post_path = '/';
    
        var post_data = querystring.stringify(dataToPost);
    
        var post_options = {
          host: post_domain,
          port: post_port,
          path: post_path,
          method: 'POST',
          headers: {
            'Content-Type': 'application/x-www-form-urlencoded',
            'Content-Length': post_data.length
          }
        };
    
        var post_req = http.request(post_options, function(res) {
          res.setEncoding('utf8');
          res.on('data', function (chunk) {
            console.log('Response: ' + chunk);
          });
        });
    
        // Handle various issues
        post_req.on('error', function(error) { // <-------------------------------- Yeah Buddy!!!
            console.log('ERROR' + error.message);
            // If you need to go on even if there is an error add below line
            //getSomething(i + 1);
        });
        post_req.on("response", function (response) {
            console.log(response);
        });
    
        // write parameters to post body
        post_req.write(post_data);
        post_req.end();
        request.on("response", function (response) {
            console.log(response);
        });
    }
    

    【讨论】:

      猜你喜欢
      • 2013-05-03
      • 2011-07-12
      • 2013-12-22
      • 2010-12-16
      • 2014-09-22
      • 2023-03-29
      • 2011-03-08
      相关资源
      最近更新 更多