Angular向Java Spring Boot Socket.IO服务端收发事件失败求助
问题描述
我在Angular 14应用中尝试向Java Spring Boot的Socket.IO服务端发送事件,目前应用能正常连接服务端,Java端也能捕获连接、断开事件,但无法向服务端发送事件,也接收不到服务端推送的事件。
使用版本:Angular 14、Java 11
预期结果:服务端能接收客户端发送的事件,客户端能收到服务端发送的事件内容
Java服务端代码(原代码)
public class SocketIOServerImpl { public static void main(String[] args) throws InterruptedException { Configuration config = new Configuration(); config.setHostname("localhost"); config.setPort(8090); websocket final SocketIOServer server = new SocketIOServer(config); server.addConnectListener(socketIOClient -> { System.out.println("User Connected"); server.getBroadcastOperations().sendEvent("daniyal", "You Connected to Server Successfully"); }); server.addDisconnectListener(client -> { server.getBroadcastOperations().sendEvent("daniyal", "You Connected to Server Successfully"); }); server.addEventListener("daniyal", String.class, new DataListener<String>() { @Override public void onData(SocketIOClient socketIOClient, String s, AckRequest ackRequest) throws Exception { System.out.println("User Connected"); server.getBroadcastOperations().sendEvent("daniyal", "You Emited STH to Server Successfully"); } }); server.start(); Thread.sleep(Integer.MAX_VALUE); server.stop(); } }
Angular Socket服务代码(原代码)
@Injectable({ providedIn: 'root' }) export class SocketServiceService { readonly uri: string = 'ws://localhost:8090'; socket: any; constructor() { this.socket = io.connect(this.uri,{ transports: [ 'websocket' ] }); } listen(eventName: string) { return new Observable((subscriber) => { this.socket.on(eventName, (data: any) => { subscriber.next(data); }); }); } emit(eventName: string, data: any) { this.socket.emit(eventName, data); } }
Angular组件代码(原代码)
@Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent implements OnInit { constructor(private socketService: SocketServiceService) { } ngOnInit() { this.socketService.listen('daniyal').subscribe( (res) => { console.log('Server Response: ',res); }); } emit(){ this.socketService.emit('daniyal','HI SERVER'); } }
问题排查与修复方案
核心问题:版本兼容性
Socket.IO的协议在不同大版本间不兼容,必须保证Java端的netty-socketio版本与Angular端的socket.io-client版本完全匹配(比如均为2.x版本)。
具体修改点
1. Java服务端修改
- 移除代码中多余的
websocket字符串(会导致配置错误) - 修正断开连接事件的错误消息
- 事件监听中打印正确的客户端消息日志
- 针对当前连接客户端发送事件(而非广播给所有用户,除非业务需要)
- 确保Maven依赖使用兼容版本(比如2.5.0):
<dependency> <groupId>com.corundumstudio.socketio</groupId> <artifactId>netty-socketio</artifactId> <version>2.5.0</version> </dependency>
修改后的Java代码:
public class SocketIOServerImpl { public static void main(String[] args) throws InterruptedException { Configuration config = new Configuration(); config.setHostname("localhost"); config.setPort(8090); final SocketIOServer server = new SocketIOServer(config); server.addConnectListener(socketIOClient -> { System.out.println("User Connected"); // 仅向当前连接的客户端发送事件 socketIOClient.sendEvent("daniyal", "You Connected to Server Successfully"); }); server.addDisconnectListener(client -> { System.out.println("User Disconnected"); client.sendEvent("daniyal", "You Disconnected from Server"); }); server.addEventListener("daniyal", String.class, (socketIOClient, s, ackRequest) -> { System.out.println("Received message from client: " + s); // 回复当前客户端 socketIOClient.sendEvent("daniyal", "You Emitted STH to Server Successfully"); }); server.start(); Thread.sleep(Integer.MAX_VALUE); server.stop(); } }
2. Angular端修改
- 将连接地址改为
http://localhost:8090(Socket.IO会自动处理协议升级为WebSocket) - 安装与Java端匹配的
socket.io-client版本:npm install socket.io-client@2.5.0 - 添加连接错误监听,方便排查问题
修改后的Socket服务代码:
import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; import * as io from 'socket.io-client'; @Injectable({ providedIn: 'root' }) export class SocketServiceService { readonly uri: string = 'http://localhost:8090'; socket: any; constructor() { this.socket = io.connect(this.uri, { transports: ['websocket'] }); // 监听连接错误 this.socket.on('connect_error', (error: any) => { console.error('Socket connection error:', error); }); // 监听连接成功 this.socket.on('connect', () => { console.log('Connected to server'); }); } listen(eventName: string): Observable<any> { return new Observable((subscriber) => { this.socket.on(eventName, (data: any) => { subscriber.next(data); }); }); } emit(eventName: string, data: any): void { this.socket.emit(eventName, data); } }
3. 组件模板补充(可选)
在app.component.html中添加触发按钮,方便测试发送事件:
<button (click)="emit()">Send Message to Server</button>
内容的提问来源于stack exchange,提问作者DaniyalVaghar
相关产品推荐
相关产品推荐

