使用Express和nodejs使用socket.io-client将查询发送到java服务器

我有一个基于Express的Web应用程序。 nodejs后端正在使用java服务器执行一些繁重的操作。 Express和java服务器之间的对话是使用socketio完成的。 nodejs服务器是客户端,使用socket.io-client向java服务器发送查询。 javaserver基于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!'行)。 没有错误消息。

奇怪的部分是,如果我第一次运行我的Web应用程序,抛出一个查询,然后启动我的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服务器上。 这是骷髅:

 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."); } } 

我的web应用程序nodejs后端和我的java服务器运行在同一台机器上,与socket.io的通信通过localhost:8080完成。 再一次,奇怪的是客户端的脚本在express框架之外使用时,这让我觉得这可能是socket.io-client和Express之间的兼容性问题。

编辑2

我修改了我的socket.io客户端代码,看到更多的细节发生了什么,我补充说:

  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"); }); 

当我closuresjava服务器运行客户端,我得到一个“connect_error”事件。 当java服务器打开时,我根本没有收到消息。 看起来连接既没有失败也没有成功,什么都没有发生……关于如何更好地debugging这个问题的想法?

编辑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"); }); } 

你的控制器的结构有点搞砸了。 以下是一些错误的东西:

  1. 您在加载模块时连接到Java服务器,但是直到命中路由时才分配connect事件处理程序。 这意味着除非服务器还没有运行,否则通常会错过连接事件。 所以,这完全解释了你所观察到的。 如果在启动Express服务器时Java服务器已经启动,则会错过连接事件,因此您绝对不会执行get_processed_data()函数中的任何逻辑。

  2. 每次路由被击中时,您都会安装一个新的连接处理程序,这意味着您将分配多个事件处理程序,但由于第一个问题,它们都不会被打中。

如果你想连接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连接,你可以在你的请求/响应中使用某种ID,这样你就可以知道哪个响应属于哪个请求。 我已经展示了如何在快速服务器中工作。 从你的Java服务器,你必须在Express服务器的响应中回显transactionId,以便跟踪哪个请求响应哪个响应。

就像你的代码一样,如果同时处理'/api/getProcessedData'路由的多个请求,那么来自不同请求的响应可能很容易混淆。 这是你做事情的架构问题。


我不是Java专家,但它看起来像这样一行:

 Thread.sleep(60000*3); 

将睡眠你的线程180,000毫秒(3分钟),然后在你的代码调用server.stop() 。 所以,你的Java服务器在3分钟后closures。

因此,您只能在启动后的3分钟内连接到Java服务器。

这里合乎逻辑的问题是,为什么你要停止你的服务器呢?