我正在尝试使用 Spring boot 设置一个 Socket.IO 服务器,它也充当我的应用程序的 API。我有一个 Angular 前端,如下所示:
问题是当我调用服务进行连接时,它会调用 Spring 的 onConnected 方法两次。我尝试通过删除对 client.joinRoom(sessionCode) 方法的调用来简化它,但日志保持不变。
我的客户端或我设置 socket.io 服务器的方式是否有错误?
我尝试将重新连接事件添加到我的客户端,并删除事件“连接”。 我尝试使用节点服务器,它工作得很好,但是它太复杂了,无法在 3 个应用程序之间进行通信,我想在 Spring 中实现。
成分:
import { Component, HostBinding, OnInit } from "@angular/core";
import { FormBuilder, FormGroup, Validators } from "@angular/forms";
import { GameSessionService } from "../../services/game-session.service";
import { SocketService } from "../../services/socket.service";
import { GameSessionI } from "../../interfaces/GameSessionI";
@Component({
selector: 'app-create-game',
templateUrl: './create-game.page.html',
styleUrl: './create-game.page.scss',
})
export class CreateGamePage implements OnInit {
createGameForm: FormGroup;
@HostBinding('class') class = 'tw-my-auto';
colorPrimaryString: string = 'primary';
colorGreyString: string = 'grey';
username: string = '';
constructor(fb: FormBuilder, private readonly gameSessionService : GameSessionService, private readonly socketService: SocketService) {
this.createGameForm = fb.group({
username: ['', Validators.required],
});
}
ngOnInit(): void {}
onSubmit() {
this.gameSessionService.createGameSession(
this.createGameForm.value.username,
).subscribe(
(gameSession: GameSessionI) => {
console.log(gameSession);
this.socketService.connect(gameSession.code, gameSession.owner.id, gameSession.owner.name);
},
);
}
backButton(){
this.socketService.disconnect();
}
}
服务:
import { Injectable } from '@angular/core';
import { io } from 'socket.io-client';
import { LaunchSessionDTO } from '../model/socket/LaunchSessionDTO';
import { GameSessionService } from './game-session.service';
@Injectable({
providedIn: 'root',
})
export class SocketService {
socket: any;
constructor(private readonly gameSessionService: GameSessionService) {
}
connect(sessionCode: string, userId: number, userName: string) {
console.log(this.socket);
if (!this.socket) {
this.socket = io('http://localhost:9092', {
transports: ['websocket'], // Specify transport for compatibility
query: { sessionCode, userId, userName }, // Include handshake data
});
this.socket.on('connect', () => {
console.log('Connected to socket server');
});
this.socket.on('disconnect', () => {
console.log('Disconnected from socket server');
});
}
}
public launchSession(launchSessionDTO: LaunchSessionDTO) {
this.socket.emit('launch_session', launchSessionDTO);
}
disconnect() {
if (this.socket) {
this.socket.disconnect();
}
}
}
package com.miage.beeramideback.socket.gamesession;
// imports
@Component
public final class GameSessionSocketModule {
private final GameSessionBasicEventSocketService gameSessionSocketService;
private final GameSessionService gameSessionService;
private final GameSessionManagementService gameSessionManagementService;
private final SocketIOServer server;
Logger log = LoggerFactory.getLogger(GameSessionManagementServiceImpl.class);
//Constructeur de la classe GameSessionSocketModule
public GameSessionSocketModule(SocketIOServer server, GameSessionSocketServiceImpl gameSessionSocketServiceImpl, GameSessionManagementServiceImpl gameSessionManagementServiceImpl, GameSessionService gameSessionService) {
this.server = server;
this.gameSessionSocketService = gameSessionSocketServiceImpl;
this.gameSessionManagementService = gameSessionManagementServiceImpl;
this.gameSessionService = gameSessionService;
//Ajout de Listener d'événements sur les parties en cours (réagit aux actions des clients connectés au serveur via le socket)
server.addConnectListener(this.onConnected());
server.addDisconnectListener(this.onDisconnected());
}
//Détecteur de l'événement de connection d'un joueur à la session
private ConnectListener onConnected() {
return (client) -> {
final var params = client.getHandshakeData().getUrlParams();
final String sessionCode = params.get("sessionCode").stream().collect(Collectors.joining());
final Long userId = Long.parseLong(params.get("userId").stream().collect(Collectors.joining()));
final String userName = params.get("userName").stream().collect(Collectors.joining());
log.info("Socket connecting '{}' ", client.getSessionId().toString());
};
}
//Détecteur de l'événement de déconnection d'un joueur à la session
private DisconnectListener onDisconnected() {
return client -> {
final var params = client.getHandshakeData().getUrlParams();
final Long userId = Long.parseLong(params.get("userId").stream().collect(Collectors.joining()));
final String sessionCode = client.getHandshakeData().getSingleUrlParam("sessionCode");
final String userName = params.get("userName").stream().collect(Collectors.joining());
log.info("Client '{}'' - disconnected from socket", client.getSessionId().toString());
};
}
}
以下是 spring 在前面调用 connect 时的日志: 日志
这似乎是库中的一个错误,解决方案是不要使用默认名称空间(“/”)并使用另一个名称空间,例如:
SocketIONamespace agentsNamespace = socketIOServer.addNamespace("/agents");
在客户端,使用此网址:
localhost:8090/agents