将 socket.io-client 与 Express 和 nodejs 一起使用,将查询发送到 java 服务器
Use socket.io-client with Express and nodejs to send query to java server
我有一个基于 Express 构建的网络应用程序。 nodejs 后端使用 java 服务器来执行一些繁重的操作。 Express 和 java 服务器之间的对话是使用 socketio 完成的。 nodejs 服务器是客户端,使用 socket.io-client 向 java 服务器发送查询。 java 服务器基于 netty-socketio。
这是我在我的 nodejs 应用程序中所做的:
var io = require('socket.io-client')
var socket = io.connect('http://localhost:8080');
socket.on('connect', function () {
console.log('0 Connected!');
socket.emit('myEvent', ['0' ,'here is the query'], function (data) {
console.log('\tSending query ... waiting for ACK0');
console.log(data);
});
socket.on('serverResponse', function (data) {
console.log('\tserverResponse event triggered, data:');
console.log(data);
});
});
在我的 Web 应用程序外部调用此脚本时,一切正常,但当我从 express 调用此代码时,我的客户端无法连接(我没有到达“0 Connected!”行)。没有错误消息。
奇怪的是,如果我先 运行 安装我的网络应用程序,抛出一个查询,然后启动我的 java 服务器,客户端会连接到 java 服务器一切正常(仅针对该查询)。关于如何解决这个问题的任何线索?
编辑 1
这是我想要实现的目标的架构:
client javascript backend java server
via browser <---> node/Express/socketio-client <---> netty-socketio
@client's machine | @my server | @my server (the same)
| |
myDNS:80 localhost:8080
java 服务器上的精度更高。这是 squeleton:
public class App {
public static void main(String[] args) throws InterruptedException, UnsupportedEncodingException {
Configuration config = new Configuration();
config.setHostname("localhost");
config.setPort(8080);
final SocketIOServer server = new SocketIOServer(config);
server.addEventListener("myEvent", String[].class, new DataListener<String[]>() {
@Override
public void onData(final SocketIOClient client, String[] data, final AckRequest ackRequest) {
//Id of the client
String id = data[0];
//Acknowledge the request:
ackRequest.sendAckData("ACK_"+id);
//doing some calculations ...
// ... ... ...
// ... ... ...
client.sendEvent("serverResponse", new VoidAckCallback(){
@Override
protected void onSuccess() {}
}, "I am the answer from the server");
}
});
server.start();
System.out.println("[JAVA SERVER INFO] Java server started.");
Thread.sleep(60000*3);//Integer.MAX_VALUE);
server.stop();
System.out.println("[JAVA SERVER INFO] Java server stopped.");
}
}
我的网络应用程序 nodejs 后端和我的 java 服务器 运行 在同一台机器上,与 socket.io 的通信是通过 localhost:8080 完成的。再一次,奇怪的是客户端的脚本在 express 框架之外使用时可以正常工作,这让我认为这可能是 socket.io-client 和 Express 之间的兼容性问题。
编辑 2
我修改了我的 socket.io-client 代码以查看更多详细信息,我添加了:
socket.on('connect_error', function(err){
console.log(err);
});
socket.on('connect_timeout', function(){
console.log("connect_timeout");
});
socket.on('reconnect_attempt', function(){
console.log("reconnect_attempt");
});
当我 运行 关闭 java 服务器的客户端时,我得到一个 'connect_error' 事件。当 java 服务器开启时,我根本收不到任何消息。似乎连接既没有失败也没有成功,什么也没发生……关于如何更好地调试它有什么想法吗?
编辑 3
这是我用来处理浏览器请求的代码:
index.js:
var express = require('express');
var router = express.Router();
var controller = require('../controllers/myController.js');
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index', { title: 'Express' });
});
module.exports = router;
router.post('/api/getProcessedData', function(req, res, next){
var text = req.body.text;
controller.get_processed_data(text, res);
});
myController.js:
var socket = require('socket.io-client')('http://localhost:8080');
module.exports.get_processed_data = function(text, res) {
var timestamp = new Date().getTime();
console.log('starting client');
socket.on('connect', function () {
console.log("client connected.");
socket.emit('myEvent', [timestamp ,text], function (data) {
console.log('\tSending query ... waiting for ACK');
console.log(data);
});
socket.on('serverResponse', function (data) {
console.log('\tserverResponse' event trigged, data:');
res.send(data);
});
});
socket.on('connect_error', function(err){
console.log(err);
});
socket.on('connect_timeout', function(){
console.log("connect_timeout");
});
socket.on('reconnect_attempt', function(){
console.log("reconnect_attempt");
});
socket.on('reconnecting', function(){
console.log("reconnecting");
});
}
你的控制器结构有点乱。以下是一些错误的地方:
您在加载模块时连接到 Java 服务器,但在路由被命中之前您不会分配 connect
事件处理程序。这意味着您通常会错过连接事件,除非服务器尚未 运行。所以,这完全解释了你所观察到的。如果在您启动 Express 服务器时 java 服务器已经启动,您将错过连接事件,因此您永远不会执行 get_processed_data()
函数中的任何逻辑。
每次路由被命中时您都安装一个新的连接处理程序,这意味着您将分配多个事件处理程序,但由于第一个问题,其中 none 个可能会被命中.
如果您希望 socket.io 连接持续连接,这将是重写控制器的一种方法:
var socket = require('socket.io-client')('http://localhost:8080');
socket.on('connect', function () {
console.log("client connected.");
});
socket.on('connect_error', function(err){
console.log(err);
});
socket.on('connect_timeout', function(){
console.log("connect_timeout");
});
socket.on('reconnect_attempt', function(){
console.log("reconnect_attempt");
});
socket.on('reconnecting', function(){
console.log("reconnecting");
});
var transactionCntr = 0;
module.exports.get_processed_data = function(text, res) {
var timestamp = new Date().getTime();
var transactionId = transactionCntr++;
console.log('sending data to client');
function onResponse(data) {
// for concurrency reasons, make sure this is the right
// response. The server must return the same
// transactionId that it was sent
if (data.transactionId === transactionId) {
console.log('\tserverResponse' event trigged, data:');
res.send(data);
socket.off('serverResponse', onResponse);
}
}
socket.on('serverResponse', onResponse);
// send data and transactionId
socket.emit('myEvent', [timestamp ,text, transactionId], function (data) {
console.log('\tSending query ... waiting for ACK');
console.log(data);
});
}
您当前的结构存在问题,因为它似乎无法确定哪个响应与哪个请求相关,并且可能存在并发问题。每次只使用一个单独的 http 请求会更简单,因为这样响应将与适当的请求唯一配对。
通过 socket.io 连接,您可以在 request/response 中使用某种 ID,这样您就可以分辨哪个响应属于哪个请求。我已经展示了它在 express 服务器中的工作原理。从您的 Java 服务器,您必须将 transactionId 回显到 Express 服务器的响应中,以便它可以跟踪哪个响应与哪个请求。
正如您的代码一样,如果 '/api/getProcessedData'
路线的多个请求同时在进行,来自不同请求的响应很容易混淆。这是您做事方式的架构问题。
我不是 Java 专家,但在我看来是这样的:
Thread.sleep(60000*3);
将使您的线程休眠 180,000 毫秒(3 分钟),然后您的代码立即调用 server.stop()
。因此,您的 Java 服务器会在 3 分钟后自行关闭。
因此,您只能在启动后的前 3 分钟内连接到您的 Java 服务器。
这里的逻辑问题是你为什么要停止你的服务器?
我有一个基于 Express 构建的网络应用程序。 nodejs 后端使用 java 服务器来执行一些繁重的操作。 Express 和 java 服务器之间的对话是使用 socketio 完成的。 nodejs 服务器是客户端,使用 socket.io-client 向 java 服务器发送查询。 java 服务器基于 netty-socketio。
这是我在我的 nodejs 应用程序中所做的:
var io = require('socket.io-client')
var socket = io.connect('http://localhost:8080');
socket.on('connect', function () {
console.log('0 Connected!');
socket.emit('myEvent', ['0' ,'here is the query'], function (data) {
console.log('\tSending query ... waiting for ACK0');
console.log(data);
});
socket.on('serverResponse', function (data) {
console.log('\tserverResponse event triggered, data:');
console.log(data);
});
});
在我的 Web 应用程序外部调用此脚本时,一切正常,但当我从 express 调用此代码时,我的客户端无法连接(我没有到达“0 Connected!”行)。没有错误消息。
奇怪的是,如果我先 运行 安装我的网络应用程序,抛出一个查询,然后启动我的 java 服务器,客户端会连接到 java 服务器一切正常(仅针对该查询)。关于如何解决这个问题的任何线索?
编辑 1
这是我想要实现的目标的架构:
client javascript backend java server
via browser <---> node/Express/socketio-client <---> netty-socketio
@client's machine | @my server | @my server (the same)
| |
myDNS:80 localhost:8080
java 服务器上的精度更高。这是 squeleton:
public class App {
public static void main(String[] args) throws InterruptedException, UnsupportedEncodingException {
Configuration config = new Configuration();
config.setHostname("localhost");
config.setPort(8080);
final SocketIOServer server = new SocketIOServer(config);
server.addEventListener("myEvent", String[].class, new DataListener<String[]>() {
@Override
public void onData(final SocketIOClient client, String[] data, final AckRequest ackRequest) {
//Id of the client
String id = data[0];
//Acknowledge the request:
ackRequest.sendAckData("ACK_"+id);
//doing some calculations ...
// ... ... ...
// ... ... ...
client.sendEvent("serverResponse", new VoidAckCallback(){
@Override
protected void onSuccess() {}
}, "I am the answer from the server");
}
});
server.start();
System.out.println("[JAVA SERVER INFO] Java server started.");
Thread.sleep(60000*3);//Integer.MAX_VALUE);
server.stop();
System.out.println("[JAVA SERVER INFO] Java server stopped.");
}
}
我的网络应用程序 nodejs 后端和我的 java 服务器 运行 在同一台机器上,与 socket.io 的通信是通过 localhost:8080 完成的。再一次,奇怪的是客户端的脚本在 express 框架之外使用时可以正常工作,这让我认为这可能是 socket.io-client 和 Express 之间的兼容性问题。
编辑 2
我修改了我的 socket.io-client 代码以查看更多详细信息,我添加了:
socket.on('connect_error', function(err){
console.log(err);
});
socket.on('connect_timeout', function(){
console.log("connect_timeout");
});
socket.on('reconnect_attempt', function(){
console.log("reconnect_attempt");
});
当我 运行 关闭 java 服务器的客户端时,我得到一个 'connect_error' 事件。当 java 服务器开启时,我根本收不到任何消息。似乎连接既没有失败也没有成功,什么也没发生……关于如何更好地调试它有什么想法吗?
编辑 3
这是我用来处理浏览器请求的代码:
index.js:
var express = require('express'); var router = express.Router(); var controller = require('../controllers/myController.js'); /* GET home page. */ router.get('/', function(req, res, next) { res.render('index', { title: 'Express' }); }); module.exports = router; router.post('/api/getProcessedData', function(req, res, next){ var text = req.body.text; controller.get_processed_data(text, res); });
myController.js:
var socket = require('socket.io-client')('http://localhost:8080'); module.exports.get_processed_data = function(text, res) { var timestamp = new Date().getTime(); console.log('starting client'); socket.on('connect', function () { console.log("client connected."); socket.emit('myEvent', [timestamp ,text], function (data) { console.log('\tSending query ... waiting for ACK'); console.log(data); }); socket.on('serverResponse', function (data) { console.log('\tserverResponse' event trigged, data:'); res.send(data); }); }); socket.on('connect_error', function(err){ console.log(err); }); socket.on('connect_timeout', function(){ console.log("connect_timeout"); }); socket.on('reconnect_attempt', function(){ console.log("reconnect_attempt"); }); socket.on('reconnecting', function(){ console.log("reconnecting"); }); }
你的控制器结构有点乱。以下是一些错误的地方:
您在加载模块时连接到 Java 服务器,但在路由被命中之前您不会分配
connect
事件处理程序。这意味着您通常会错过连接事件,除非服务器尚未 运行。所以,这完全解释了你所观察到的。如果在您启动 Express 服务器时 java 服务器已经启动,您将错过连接事件,因此您永远不会执行get_processed_data()
函数中的任何逻辑。每次路由被命中时您都安装一个新的连接处理程序,这意味着您将分配多个事件处理程序,但由于第一个问题,其中 none 个可能会被命中.
如果您希望 socket.io 连接持续连接,这将是重写控制器的一种方法:
var socket = require('socket.io-client')('http://localhost:8080');
socket.on('connect', function () {
console.log("client connected.");
});
socket.on('connect_error', function(err){
console.log(err);
});
socket.on('connect_timeout', function(){
console.log("connect_timeout");
});
socket.on('reconnect_attempt', function(){
console.log("reconnect_attempt");
});
socket.on('reconnecting', function(){
console.log("reconnecting");
});
var transactionCntr = 0;
module.exports.get_processed_data = function(text, res) {
var timestamp = new Date().getTime();
var transactionId = transactionCntr++;
console.log('sending data to client');
function onResponse(data) {
// for concurrency reasons, make sure this is the right
// response. The server must return the same
// transactionId that it was sent
if (data.transactionId === transactionId) {
console.log('\tserverResponse' event trigged, data:');
res.send(data);
socket.off('serverResponse', onResponse);
}
}
socket.on('serverResponse', onResponse);
// send data and transactionId
socket.emit('myEvent', [timestamp ,text, transactionId], function (data) {
console.log('\tSending query ... waiting for ACK');
console.log(data);
});
}
您当前的结构存在问题,因为它似乎无法确定哪个响应与哪个请求相关,并且可能存在并发问题。每次只使用一个单独的 http 请求会更简单,因为这样响应将与适当的请求唯一配对。
通过 socket.io 连接,您可以在 request/response 中使用某种 ID,这样您就可以分辨哪个响应属于哪个请求。我已经展示了它在 express 服务器中的工作原理。从您的 Java 服务器,您必须将 transactionId 回显到 Express 服务器的响应中,以便它可以跟踪哪个响应与哪个请求。
正如您的代码一样,如果 '/api/getProcessedData'
路线的多个请求同时在进行,来自不同请求的响应很容易混淆。这是您做事方式的架构问题。
我不是 Java 专家,但在我看来是这样的:
Thread.sleep(60000*3);
将使您的线程休眠 180,000 毫秒(3 分钟),然后您的代码立即调用 server.stop()
。因此,您的 Java 服务器会在 3 分钟后自行关闭。
因此,您只能在启动后的前 3 分钟内连接到您的 Java 服务器。
这里的逻辑问题是你为什么要停止你的服务器?