我正在尝试在node.js中编写一个小型中继脚本,用于侦听本地套接字上的传入TCP连接,当它获得一个时,将流量转发给第三方。它还必须从第三方获取任何返回的数据并将其发送回原始本地套接字。我尝试过类似http://delog.wordpress.com/2011/07/19/a-tcp-relay-mechanism-with-node-js/的代码并且它确实有效,但它要求发送方是一个正在侦听套接字本身的服务器,而我的实用程序适用于尝试创建出站TCP连接的任何程序。不幸的是,我遇到的问题是,一旦客户端将数据发送到“路由器”程序,路由器将数据转发到另一台服务器,然后从客户端返回数据,一切都很好。但是,当客户端程序结束或终止并尝试重新连接时,我得到了这个:
events.js:72
throw er; // Unhandled 'error' event
^
Error: This socket has been ended by the other party
at Socket.writeAfterFIN [as write] (net.js:275:12)
at Socket.<anonymous> (/root/tcp_loop.js:37:17)
at Socket.emit (events.js:117:20)
at Socket.<anonymous> (_stream_readable.js:748:14)
at Socket.emit (events.js:92:17)
at emitReadable_ (_stream_readable.js:410:10)
at emitReadable (_stream_readable.js:406:5)
at readableAddChunk (_stream_readable.js:168:9)
at Socket.Readable.push (_stream_readable.js:130:10)
at TCP.onread (net.js:528:21)
我删除了所有逻辑并将测试用例提炼成一小段代码:一个服务器充当路由器(侦听端口8124)以及“远程”服务器(端口9999),虽然我的测试表明它没有天气,远程服务器在同一台机器上,在互联网上等。这是服务器代码:
var net = require('net'),
util = require('util')
;
// The loop_server simulates a remote service.
// The error occurs whether using it here, or actually forwarding
// the data to a remote host.
var loop_server = net.createServer(function(loop) {
console.log("Loop server connected");
loop.on("end", function() {
console.log("Loop server disconnected");
});
loop.on("data", function(data) {
console.log("Loop got data: " + data);
loop.write(data);
});
}).listen(9999, function() {
console.log("Loop server bound");
});
var remote_socket = net.connect(9999, function() {
console.log("Remote connected");
var local_server = net.createServer(function(local_socket) { //'connection' listener
console.log('Local server connected');
local_socket.on('end', function() {
console.log('Local server disconnected');
// local_socket.destroy();
});
local_socket.on('data', function(ldata) {
console.log("Local socket got data: " + ldata);
remote_socket.write(ldata);
});
remote_socket.on('data', function(rdata) {
console.log("Remote socket got data: " + rdata);
local_socket.write(rdata);
});
local_socket.write('hello\r\n');
}).listen(8124, function() { //'listening' listener
console.log('Local server bound');
});
}); // remote_socket
失败的是local_socket.write(rdata);
处理程序中的remote_socket.on('data', ...
。它在路由器第一次启动并且客户端连接时工作,但永远不会再次启动。
供参考,这是我一直在使用的小客户端应用程序的代码。我使用perl脚本,telnet等获得相同的结果:
var net = require('net');
var client = new net.Socket();
client.connect(8124, function() {
console.log('CONNECTED TO: localhost:8124');
client.write('Single text message from the client app');
});
client.on('data', function(data) {
console.log('DATA: ' + data);
});
client.on('close', function() {
sconsole.log('Connection closed');
});
非常感谢任何见解。我觉得我必须在这里找到一些非常简单的东西...
更新
下面的Nitzin解决方案是一种更好的方法,但在我下面的特定示例中,解决方案是在创建新的remote_socket.on('data')
侦听器之前删除它们,例如:
var remote_socket = net.connect(9999, function() {
console.log("Remote connected");
var local_server = net.createServer(function(local_socket) { //'connection' listener
console.log('Local server connected');
remote_socket.removeAllListeners('data');
...
remote_socket.on('data', function(rdata) {
console.log("Remote socket got data: " + rdata);
local_socket.write(rdata);
});
答案 0 :(得分:2)
你不应该destroy
套接字。它关闭套接字的两端。你应该只.end()
它,它会结束你的写作结束。
修改强>
正如我最初写的那样,销毁套接字是不好的,但你真正的问题是完全不同的:你得到了你的代理(你所谓的#34;本地&#34;)和回声(你所谓的#34;远程&#34;)服务器向后:代理服务器应该为代理服务器获得的每个新连接建立到 echo 服务器的新连接,而不是与您相反的方式现在就拥有它。
客户端只需要end()
,让服务器知道你已经完成了写作。
以下是client.js
:
var net = require('net');
var client = new net.Socket();
client.connect(8124, function() {
console.log('CLIENT: CONNECTED: localhost:8124');
client.write('single text message from the client app');
client.end();
});
client.on('data', function(data) {
console.log('CLIENT: GOT DATA: ' + data);
});
client.on('close', function() {
console.log('CLIENT: CONNECTION CLOSED');
});
这是servers.js
:
var net = require('net'),
util = require('util');
net.createServer(function(conn) {
console.log('ECHO_SERVER: CONN: new connection');
conn.on('end', function() {
console.log('ECHO_SERVER: CONN: disconnected');
});
conn.on('data', function(data) {
console.log('ECHO_SERVER: CONN: GOT DATA: ' + data);
conn.write(data);
});
}).listen(9999, function() {
console.log('ECHO_SERVER STARTED');
});
net.createServer(function(conn) {
console.log('PROXY_SERVER: CONN: new connection');
var remote = net.connect(9999, function() {
console.log('PROXY_SERVER: CONNECTED TO ECHO_SERVER');
conn.on('end', function() {
console.log('PROXY_SERVER: CONN: disconnected');
remote.end();
});
conn.on('data', function(data) {
console.log('PROXY_SERVER: CONN: GOT DATA FOR ECHO_SERVER: ' + data);
remote.write(data);
});
remote.on('data', function(data) {
console.log('PROXY_SERVER: CONN: GOT DATA FROM ECHO_SERVER: ' + data);
conn.write(data);
});
});
}).listen(8124, function() {
console.log('PROXY_SERVER STARTED');
});
如您所见,代理服务器的每个conn
都有一个新的remote
进入echo服务器。