在运行Socket.io服务器时,我面临一个问题,使用Next.js抛出Express.js服务器。
没有连接任何客户端的服务器发送错误。但是客户端可以通过浏览器连接,没有任何问题.
以下是服务器正在运行的控制台上的错误:
Socket error TransportError: xhr poll error
at Polling.onError (/Users/cedricbapst/Projects/gynemanager-frontend-next/node_modules/engine.io-client/build/cjs/transport.js:46:37)
at Request.<anonymous> (/Users/cedricbapst/Projects/gynemanager-frontend-next/node_modules/engine.io-client/build/cjs/transports/polling.js:255:18)
at Request.Emitter.emit (/Users/cedricbapst/Projects/gynemanager-frontend-next/node_modules/@socket.io/component-emitter/index.js:143:20)
at Request.onError (/Users/cedricbapst/Projects/gynemanager-frontend-next/node_modules/engine.io-client/build/cjs/transports/polling.js:356:14)
at Timeout._onTimeout (/Users/cedricbapst/Projects/gynemanager-frontend-next/node_modules/engine.io-client/build/cjs/transports/polling.js:329:30)
at listOnTimeout (node:internal/timers:559:17)
at processTimers (node:internal/timers:502:7) {
description: 0,
context: XMLHttpRequest {
UNSENT: 0,
OPENED: 1,
HEADERS_RECEIVED: 2,
LOADING: 3,
DONE: 4,
readyState: 4,
onreadystatechange: [Function (anonymous)],
responseText: 'Error: getaddrinfo ENOTFOUND undefined\n' +
' at GetAddrInfoReqWrap.onlookup [as oncomplete] (node:dns:71:26)',
responseXML: '',
status: 0,
statusText: Error: getaddrinfo ENOTFOUND undefined
at GetAddrInfoReqWrap.onlookup [as oncomplete] (node:dns:71:26) {
errno: -3008,
code: 'ENOTFOUND',
syscall: 'getaddrinfo',
hostname: 'undefined'
},
open: [Function (anonymous)],
setDisableHeaderCheck: [Function (anonymous)],
setRequestHeader: [Function (anonymous)],
getResponseHeader: [Function (anonymous)],
getAllResponseHeaders: [Function (anonymous)],
getRequestHeader: [Function (anonymous)],
send: [Function (anonymous)],
handleError: [Function (anonymous)],
abort: [Function (anonymous)],
addEventListener: [Function (anonymous)],
removeEventListener: [Function (anonymous)],
dispatchEvent: [Function (anonymous)]
},
type: 'TransportError'
}
socket.io-client:manager reconnect attempt error +1ms
socket.io-client:manager will wait 5000ms before reconnect attempt +0ms
首先要说明的是,此错误不是在客户端,而是在服务器上,浏览器中的客户端甚至与服务器上的错误都有工作连接。客户端没有任何错误,工作正常。
以下是我的express.js服务器代码:
import express, {Express} from 'express';
import * as http from 'http';
import next, {NextApiHandler} from 'next';
import passport from 'passport';
import session, {SessionOptions} from 'express-session';
import {Options} from "session-file-store";
const FileStore = require('session-file-store')(session);
import uid from 'uid-safe';
import bodyParser from 'body-parser';
import routes from './routes';
import SocketServer from "../socketio/SocketServer";
import socketMiddleware from "../socketio/SocketMiddleware";
const port: number = parseInt(process.env.PORT || '3000', 10);
const dev: boolean = process.env.NODE_ENV !== 'production';
const nextApp = next({ dev });
const nextHandler: NextApiHandler = nextApp.getRequestHandler();
nextApp.prepare().then(() => {
const app: Express = express();
const server: http.Server = http.createServer(app);
// Socket io server
const socketServer = new SocketServer(server);
// Session
const fileStoreOptions: Options = {
path: './.next/session' // register session folder in .next folder
};
const sessionConfig: SessionOptions = {
//secret: uid.sync(18),
genid: (req) => {
return 'app_' + uid.sync(18) // use UUIDs for session IDs
},
secret: 'SECRET',
cookie: {
maxAge: 43200 * 1000 // 12h
},
resave: false,
saveUninitialized: true,
store: new FileStore(fileStoreOptions)
};
app.use(bodyParser.json());
app.use(session(sessionConfig));
passport.serializeUser((user: any, done: (a: any, b: string) => void) => done(null, user));
passport.deserializeUser((user: string, done: (a: any, b: any) => void) => done(null, user));
app.use(passport.initialize());
app.use(passport.session());
// Add socketio to request to have available in express routes
app.use(socketMiddleware(socketServer));
app.use('/api/auth', routes.security); // anonymous
app.use('/api/users', routes.users); // authenticated
app.use('/api/patients', routes.patients); // authenticated
app.use('/api/appointments', routes.appointments); // authenticated
app.use('/api/consultations', routes.consultations); // authenticated
app.use('/api/tasks', routes.tasks); // authenticated
app.use('/api/documents', routes.documents); // authenticated
app.use('/', routes.nextjs); // anonymous and authenticated
// Handle all nextjs route
app.all('*', (req: any, res: any) => nextHandler(req, res));
server.listen(port, () => {
console.log(`> Ready on http://localhost:${port}`);
});
});
然后我的SocketServer.ts
import {Server, Socket} from "socket.io";
import * as http from 'http';
import {ServerEvents, ClientEvents} from "./SocketEvents";
class SocketServer {
private io: Server;
public constructor(server: http.Server) {
this.io = new Server(server);
this.initServer();
}
private initServer = (): void => {
this.io.on(ServerEvents.CONNECTION, (socket: Socket) => {
this.initClient(socket);
});
}
private initClient = (socket: Socket): void => {
console.log('New client connected with id', socket.id);
// Emit status message for new connected client
socket.emit(ServerEvents.STATUS, 'Connected on Gynemanager SocketIO server');
socket.on(ClientEvents.USER_CONNECTED, async (socketId, username) => {
const sockets = await this.io.fetchSockets(); // Get all connected clients
// Add username to socket data
sockets.forEach(socket => {
if (socket.id === socketId) socket.data.username = username; // add username to new connected client
})
})
socket.on(ServerEvents.DISCONNECT, (reason: string) => {
console.log('Client disconnected', reason);
})
}
}
export default SocketServer
然后是SocketMiddleware.ts
import {Response, NextFunction} from 'express';
import SocketServer from "./SocketServer";
import {CustomRequest} from "../types/express";
const socketMiddleware = (socketServer: SocketServer) => {
return (req: CustomRequest, res: Response, next: NextFunction) => {
req.socketServer = socketServer;
next();
}
}
export default socketMiddleware;
任何帮助都将不胜感激。
发布于 2022-05-02 18:59:49
最后,我想出了我的问题所在。
我为客户端初始化了来自_app.tsx的_app.tsx连接,因为这里是我使用React提供程序将_app.tsx绑定到整个应用程序的地方。
要解决这个问题,我必须将连接初始化从_app.tsx移到另一个页面(就我的情况而言,从从登录页面重定向的页面),并检查连接是否已经插入到另一个页面中,其中还需要套接字来避免多个连接,然后一切都按预期进行。
https://stackoverflow.com/questions/72077090
复制相似问题