将 socket.io 与 Mean 集成时反复出现 404 错误

Posted

技术标签:

【中文标题】将 socket.io 与 Mean 集成时反复出现 404 错误【英文标题】:getting 404 error repeatedly when integrating socket.io with Mean 【发布时间】:2020-10-13 00:07:00 【问题描述】:

我正在尝试在数据库发生更改时自动刷新列表。到目前为止,我在控制台中反复收到此错误

所以找不到错误。

app.js

 //importing modules
const express = require('express');
const http = require('http');
const path = require('path');
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
const cors = require('cors');
const socketIO = require('socket.io');
const errorHandler = require('./_helpers/error-handler');

const app =express();

const notice = require('./controllers/noticeController');
const employee = require('./controllers/employeeController');
const users = require('./users/users.controller');

//connect mongoDb


//on connection
mongoose.connection.on('connected',()=>
    console.log('Connected to database');
);
mongoose.connection.on('error',(err)=>
    if(err)
        console.log('Error in Database Connection '+err);
    
);

const port = 3000;

//adding middleware
app.use(cors());

//body-parser
app.use(bodyParser.json());

//routes
app.use('/api', notice);
app.use('/api', employee);
app.use('/users', require('./users/users.controller'));

app.use(errorHandler);

const server = http.createServer(app);
const io = socketIO(server);
app.set('io',io);


//static files
app.use(express.static(path.join(__dirname, 'public')));

app.listen(port,()=>
    console.log('Server started at port: '+port);
);

这里是使用 socket.io 的帖子和获取 API

noticeController.js

//retrieving notice list
router.get('/notices/get',(req,res)=>
   notice.find().then((notices)=>
       res.send(notices)
   );
);

//add notice
router.post('/notice/add',(req,res,next)=>
    const io = req.app.get('io');
    let newNotice = new notice(
        title : req.body.title,
        description : req.body.description,
        image : req.body.image
    );

    newNotice.save().then(()=>
        io.emit('newNoticeAdded');
    );
);

那么任何人都可以帮助解决这个问题吗? 到客户端。我已经使用 socket-io-client 包。

ts 文件。

ngOnInit(): void 

   this.socket.on('newNoticeAdded',()=>
     this.noticeService.getNotices()
                     .subscribe(notices => 
                      this.notices = notices;
);
   );

notices 是要在更改时自动更新的列表。

【问题讨论】:

【参考方案1】:

马上,我可以发现你的代码有问题。查看以下几行:

const server = http.createServer(app);
const io = socketIO(server);
app.set('io', io);


//static files
app.use(express.static(path.join(__dirname, 'public')));

app.listen(port, ()=>
    console.log('Server started at port: '+ port);
);

这里发生了什么?好吧,我们来分析一下:

    您正在使用http.createServer(app) 创建一个HTTP,那么, 之后,您将服务器传递给socketIO() 构造函数, 您最终为您的应用设置了一些静态文件路由, 您在 express 应用上调用 app.listen 以启动 express 应用。

这里缺少什么? 您从未在您的 HTTP 服务器上调用过server.listen

你问为什么这很重要?因为您的 Socket.IO 服务器绑定到您的 HTTP 服务器,不是您的快速应用程序。由于您只是告诉您的 express 应用开始接受连接,因此您的 Socket.IO 服务器尚未启动。

要解决这个问题,您可以在 HTTP 服务器上调用 server.listen,而不是使用 express 应用,如下所示:

const server = http.createServer(app);
const io = socketIO(server);
app.set('io', io);


//static files
app.use(express.static(path.join(__dirname, 'public')));

// Notice we called the listen function on your HTTP server 
// instead of your express app. Your express app will still work
// because you passed your app to the http.createServer method
server.listen(port, ()=>
    console.log('Server started at port: '+ port);
);

哦,另外,您应该确保您的客户端代码连接到正确的地址。比如,确保连接到服务器正在侦听的地址,而不是其他地址。我这样说是因为您的错误图片显示您试图连接到端口 4200 而不是 3000,这是您的服务器正在侦听的端口。

编辑因为我看到您不确定如何将您的客户端连接到与您的服务器运行相同的端口,这里有一些代码可以帮助您。

// You could just do this, and the socket.io client
// will connect to the ```window.location```, which
// is usually what you want.
// This is good because you don't hard-code the URL
// into your code, making it easier for you to put the
// script into production.
const socket = io();

// You could also do ```io.connect```, but BEWARE,
// you have to change the URL that the socket.io client
// connects to manually, so that's why I prefer the above
// method.
const socket2 = io.connect("http://localhost:3000");

可以看到io()函数here的默认行为

希望这会有所帮助。

【讨论】:

我也尝试过使用 server.listen。仍然得到同样的错误。你能告诉我如何将前端和后端监听到相同的 3000。 您是否尝试过像这样更改您的客户端连接到localhost:3000 的方式? const socket = io.connect("http://localhost:3000");【参考方案2】:

您需要在两侧使用相同的端口。我的客户端打字稿服务(服务器使用端口 8090):

import  Injectable  from '@angular/core';

// rxjs
import  Observable  from 'rxjs';

// other
import  NGXLogger  from 'ngx-logger';
import  Event  from '../model/event';
import  environment  from '../../../environments/environment';
import * as socketIo from 'socket.io-client';

export let SERVER: string = "";
if (environment.production) 
    SERVER = 'http://10.1.1.7:8090';    // EDS Server
 else 
    SERVER = 'http://10.1.1.194:8090';  // Portalogic PC
    //SERVER = "http://" + window.location.hostname + ":8090";


@Injectable(
    providedIn: "root"
)
export class SocketService 
    debug: boolean = true;
    private socket: any;

    constructor(
        private logger: NGXLogger,
      )  

      public initSocket(): void 
        if (this.debug) 
            this.logger.debug("initialize websocket at " + SERVER);
        
        this.socket = socketIo(SERVER);
    

    public closeSocket(): void 
        this.socket.close();
    

    public sendEvent(event: Event, data?: Object): void 
        if (this.debug) 
            this.logger.debug("sendEvent >> event = " + event.toString() + "; data = " + JSON.stringify(data));
        

        this.socket.emit(event.toString(), data);
    

    public onEvent(event: Event): Observable<Event> 
        return new Observable<Event>(observer => 
            this.socket.on(event, (data: any) => observer.next(data));
        );
    

我从app.component.ts 调用initIoConnection 然后订阅onEvent 事件。

【讨论】:

那么您如何解释如何在我的代码中使用此设置 @pasindusenarath 我最初关注了这个 GitHub example。也许在 GitHub 上搜索 nodejs 示例而不是 angular/typescript。

以上是关于将 socket.io 与 Mean 集成时反复出现 404 错误的主要内容,如果未能解决你的问题,请参考以下文章

Socket.IO-client.java 反复断开重连

部署后 Socket.io 不工作 - 抛出错误 - 405(不允许)

在 MEAN 堆栈中实现 facebook / twitter 样式提要的最有效方法是啥?我应该考虑socket.io吗? [关闭]

将 socket.io 与 redux 一起使用

node.js socket.io 应用程序 - 如何将某人踢出聊天室?

在nodeJs中将pm2与socket io集成[关闭]