【问题标题】:angular SocketIoConfig websocket connection on herokuheroku上的角度SocketIoConfig websocket连接
【发布时间】:2020-02-24 14:53:20
【问题描述】:

我目前在我的 Angular 应用程序中使用 socket.io 有一个简单的 WebSocket 连接。当我通过 ng serve 运行我的代码时,它工作正常,但是在我部署到我的 Heroku 应用程序后,我收到一个“net::ERR_NAME_NOT_RESOLVED”错误。似乎在设置我的 SocketIoConfig 后,主机名更改为 null,但这仅发生在 Heroku 上。

我的 app.module.ts 中的控制台日志显示在:

  1. ng serve 正确格式为 'http://localhost:4444'
  2. Heroku 正确格式为 'https://app-name.herokuapp.com'

但是,在 Heroku 上运行时,我的控制台错误是:

获取https://null/socket.io/?EIO=3&transport=polling&t=N1tbO9M 网络::ERR_NAME_NOT_RESOLVED

为什么主机名变为空?我错过了什么?

app.enter code heremodule.ts 文件:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { HttpClientModule } from '@angular/common/http';
import { ChartsModule } from 'ng2-charts';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { HeaderComponent } from './header/header.component';

import { FlexLayoutModule } from '@angular/flex-layout';
import { PlayerStatsComponent } from './player-stats/player-stats.component';
import { playerName, filterByRole, orderHeroBy, greaterThan10m, replace } from './custom.pipe';
import { HomePageComponent } from './home-page/home-page.component';
import { WinrateComponent } from './winrate/winrate.component';
import { FormsModule } from '@angular/forms';

import { SocketIoModule, SocketIoConfig } from 'ngx-socket-io';

let port = ( window.location.hostname === 'localhost' ) ? ':8080' : '';
let url = `${window.location.protocol}//${window.location.hostname}${port}`;
const config: SocketIoConfig = { url: url, options: {} };
console.log( config );

@NgModule({
    declarations: [
        AppComponent,
        HeaderComponent,
        PlayerStatsComponent,
        playerName,
        filterByRole,
        greaterThan10m,
        orderHeroBy,
        HomePageComponent,
        WinrateComponent,
        replace
    ],
    imports: [
        HttpClientModule,
        BrowserModule,
        AppRoutingModule,
        ChartsModule,
        FlexLayoutModule,
        FormsModule,
        SocketIoModule.forRoot(config)
    ],
    providers: [],
    bootstrap: [AppComponent]
})
export class AppModule { }

server.js 文件

//Install express server
const express = require( 'express' );
const path = require( 'path' );

const http = require('http');
const https = require('https');

// webserver
const app = express();
app.use( express.static( __dirname + '/dist/statwatchII' ) );
app.get( '/*', function( req, res ) {
    res.sendFile( path.join( __dirname+'/dist/statwatchII/index.html' ) );
});

// socketserver
const port = process.env.PORT || 8080;
const server = http.Server(app);
const io = require( 'socket.io' )( server );

io.on( "connection", ws => {
    console.log( 'connected' );
} )

server.listen( port, () => { console.log( `listening on port: ${port}`) } );

【问题讨论】:

    标签: angular heroku socket.io


    【解决方案1】:

    您的应用未正确部署。

    1. ng serve 正确格式为“http://localhost:4444
    2. Heroku 的格式正确为“https://app-name.herokuapp.com:4444

    这不是真的。在 Heroku 上部署 Web 应用程序时,您不再在主机名之后显式添加端口号。 Heroku 的 DNS 自动将主机名转换为 IP 地址 + 端口号。
    此外,您无法决定端口号将是什么。

    app.listen( process.env.PORT || 8080 );
    

    通过这一行,您可以在本地主机上的http://localhost:8080/ 上提供您的网页(假设您尚未设置环境变量$PORT)。在 Heroku 上,您的网页将在 https://app-name.herokuapp.com/ 上可用

    server.listen(4444);
    

    此行将在 localhost 上运行。但它不适用于 Heroku,因为您无法明确决定您的 Web 应用程序正在运行的端口。

    您实际上不需要两个端口,因为您可以结合 http 和 ws。你可以这样做。

    const app = require('express')();
    const server = require('http').createServer(app);
    const io = require('socket.io')(server);
    io.on('connection', () => { /* … */ });
    server.listen( process.env.PORT || 8080 );
    

    我已经用类似的策略在 Heroku 上部署了 d-zone。在这里可以找到相关源码:
    https://github.com/vegeta897/d-zone/blob/63730fd7f44d2716a31fcae55990d83c84d5ffea/script/websock.js
    这是部署链接:https://heroku.com/deploy?template=https://github.com/vegeta897/d-zone/tree/heroku

    【讨论】:

    • 我已经根据您所说的重新调整了我的代码。它似乎没有改变我正在经历的行为。我现在尝试将 Web 套接字客户端连接到 Web 套接字服务器:localhost:8080(对于 dev)或 my-app.herokuapp.com。我相信问题出在我的客户端代码而不是服务器端。当我继续收到以下错误客户端时:GET null/socket.io/?EIO=3&transport=polling&t=N1uMp2l net::ERR_NAME_NOT_RESOLVED
    • 我已经用我根据您的建议尝试的最新代码更改更新了我的问题。
    【解决方案2】:

    为了让 WebSocket 客户端在 Heroku 部署中连接,我需要做两件事。

    删除 Web 套接字服务器端口号的硬编码(如上面 Tin Nguyen 所建议的)。现在这意味着该端口仅针对 localhost 进行了硬编码。

    const port = process.env.PORT || 8080;
    const server = http.Server(app);
    const io = require( 'socket.io' )( server );
    server.listen( port, () => { console.log( `listening on port: ${port}`) } );
    

    如果主机名不是 localhost,我还更新了客户端 socket.io 配置以将 URL 设置为未定义。在 socket.io 中,如果 URL 未定义,它会从源主机名手动设置它。

    let hostname = window.location.hostname;
    let url = ( hostname === 'localhost' ) ? `${window.location.protocol}//${hostname}:8080` : undefined;
    const config: SocketIoConfig = { url: url, options: {} };
    

    【讨论】:

      猜你喜欢
      • 2017-04-30
      • 2017-09-10
      • 2014-05-15
      • 2020-04-01
      • 2021-07-19
      • 2019-09-15
      • 1970-01-01
      • 2021-10-18
      • 2018-01-03
      相关资源
      最近更新 更多