Node.js 将socket.io-client与Express和nodejs一起使用,将查询发送到java服务器

Node.js 将socket.io-client与Express和nodejs一起使用,将查询发送到java服务器,node.js,express,socket.io,Node.js,Express,Socket.io,我有一个基于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('ht

我有一个基于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服务器关闭的情况下运行客户机时,我会收到一个“connect\u 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 server时java服务器已经启动,则会错过connect事件,因此您永远不会执行
      get\u processed\u data()
      函数中的任何逻辑

    • 每次点击路由时,您都会安装一个新的连接处理程序,这意味着您将分配多个事件处理程序,尽管由于第一个问题,它们中没有一个可能会被点击

    • 如果希望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,这样您就可以知道哪个响应属于哪个请求。我已经展示了在express服务器中如何工作。在Java服务器上,您必须将transactionId回显到Express服务器的响应中,以便它能够跟踪哪个响应与哪个请求一起进行

      正如您的代码一样,如果对
      '/api/getProcessedData'
      路由的多个请求同时进行,那么来自不同请求的响应很容易混淆。这是你做事方式的架构问题


      我不是Java专家,但在我看来是这样的:

      Thread.sleep(60000*3);
      
      将使线程休眠180000毫秒(3分钟),然后代码立即调用
      server.stop()
      。因此,Java服务器会在3分钟后自动关闭

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


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

      您的web应用程序运行在哪个端口上?Java服务器在哪个端口监听socket.io连接?我在最初的帖子中添加了一些信息,希望能有所帮助。如果您需要更多详细信息,请不要犹豫。这只是为了测试服务器,在最终版本中,它将是Thread.sleep(Integer.MAX_VALUE);。我只是懒惰,这样我就不必在eclipse中点击终止进程按钮。有趣的是,如果我首先运行我的节点服务器
      npm start
      ,然后从web界面抛出一个post请求,该请求将调用我的socket.io-client脚本。如果没有java服务器正在侦听
      localhost:8080
      。然后,当我启动java服务器时,就会创建连接并正确处理查询。当发出查询且没有服务器在侦听时,会发生绕过问题的情况。是否可以为发出的每个查询模拟此行为?@user3091275-是否有其他端口与8080竞争?@user3091275-能否在使用socket.io连接的Express中显示处理post操作的代码?这似乎就是问题所在。@user3091275-我添加了一个可能的编码解决方案。
      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); 
          });
      }
      
      Thread.sleep(60000*3);