|
|
@@ -0,0 +1,330 @@
|
|
|
+package com.fs.live.websocket.test;
|
|
|
+
|
|
|
+import javax.websocket.*;
|
|
|
+import java.io.IOException;
|
|
|
+import java.net.URI;
|
|
|
+import java.util.Scanner;
|
|
|
+import java.util.concurrent.CountDownLatch;
|
|
|
+import java.util.concurrent.TimeUnit;
|
|
|
+
|
|
|
+/**
|
|
|
+ * WebSocket 测试客户端
|
|
|
+ * 使用 @ClientEndpoint 注解方式
|
|
|
+ */
|
|
|
+@ClientEndpoint
|
|
|
+public class WebSocketTestClient {
|
|
|
+
|
|
|
+ private Session session;
|
|
|
+ private CountDownLatch closeLatch = new CountDownLatch(1);
|
|
|
+ private boolean connected = false;
|
|
|
+ private Throwable connectionError = null;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 连接成功回调
|
|
|
+ */
|
|
|
+ @OnOpen
|
|
|
+ public void onOpen(Session session) {
|
|
|
+ this.session = session;
|
|
|
+ this.connected = true;
|
|
|
+
|
|
|
+ System.out.println("\n✅ WebSocket 连接成功!");
|
|
|
+ System.out.println("Session ID: " + session.getId());
|
|
|
+ System.out.println("服务器地址: " + session.getRequestURI());
|
|
|
+ System.out.println("请求参数: " + session.getRequestParameterMap());
|
|
|
+ System.out.println("\n等待消息...");
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 收到消息回调
|
|
|
+ */
|
|
|
+ @OnMessage
|
|
|
+ public void onMessage(String message) {
|
|
|
+ System.out.println("\n📨 收到消息: ");
|
|
|
+ System.out.println(message);
|
|
|
+ System.out.print("> ");
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 连接关闭回调
|
|
|
+ */
|
|
|
+ @OnClose
|
|
|
+ public void onClose(CloseReason closeReason) {
|
|
|
+ System.out.println("\n❌ WebSocket 连接关闭");
|
|
|
+ System.out.println("关闭原因: " + closeReason.getReasonPhrase());
|
|
|
+ System.out.println("关闭代码: " + closeReason.getCloseCode());
|
|
|
+ this.connected = false;
|
|
|
+ closeLatch.countDown();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 错误回调
|
|
|
+ */
|
|
|
+ @OnError
|
|
|
+ public void onError(Throwable throwable) {
|
|
|
+ System.err.println("\n⚠️ WebSocket 错误:");
|
|
|
+ this.connectionError = throwable;
|
|
|
+ throwable.printStackTrace();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 发送消息
|
|
|
+ */
|
|
|
+ public void sendMessage(String message) {
|
|
|
+ if (session != null && session.isOpen()) {
|
|
|
+ try {
|
|
|
+ session.getBasicRemote().sendText(message);
|
|
|
+ System.out.println("\n📤 发送消息: " + message);
|
|
|
+ } catch (IOException e) {
|
|
|
+ System.err.println("发送消息失败: " + e.getMessage());
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ System.err.println("连接未打开或已关闭");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 关闭连接
|
|
|
+ */
|
|
|
+ public void close() {
|
|
|
+ if (session != null && session.isOpen()) {
|
|
|
+ try {
|
|
|
+ session.close(new CloseReason(CloseReason.CloseCodes.NORMAL_CLOSURE, "测试结束"));
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 检查是否已连接
|
|
|
+ */
|
|
|
+ public boolean isConnected() {
|
|
|
+ return connected && session != null && session.isOpen();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取连接错误
|
|
|
+ */
|
|
|
+ public Throwable getConnectionError() {
|
|
|
+ return connectionError;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 等待连接关闭
|
|
|
+ */
|
|
|
+ public boolean awaitClose(long timeout, TimeUnit unit) throws InterruptedException {
|
|
|
+ return closeLatch.await(timeout, unit);
|
|
|
+ }
|
|
|
+
|
|
|
+ public static void main(String[] args) {
|
|
|
+ WebSocketContainer container = null;
|
|
|
+ WebSocketTestClient client = null;
|
|
|
+
|
|
|
+ try {
|
|
|
+ // ==================== 配置区域 ====================
|
|
|
+ String host = "localhost";
|
|
|
+ int port = 7114;
|
|
|
+
|
|
|
+ // 直播间和用户配置
|
|
|
+ long liveId = 27; // ⚠️ 修改为实际存在的直播间ID
|
|
|
+ long userId = 856648; // Token 中的用户ID(sub字段)
|
|
|
+ long userType = 0; // 0=普通用户, 1=管理员
|
|
|
+
|
|
|
+ // JWT Token(从 Postman 生成)
|
|
|
+ String jwtToken = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJzdWIiOiI4NTY2NDgiLCJpYXQiOjE3NzU5NTc2OTEsImV4cCI6MTgwNzQ5MzY5MX0.keB7XqAQcGhpsKjKbaIhmFhxf2443jHUBRvRSaLjqi-igUaPGA37dUBLJ65R89h6g-7pGr-4Cn99GhvnmkpdpQ";
|
|
|
+ String jwtHeader = "AppToken"; // JWT header 参数名
|
|
|
+
|
|
|
+ // 可选参数
|
|
|
+ Long companyId = -1L;
|
|
|
+ Long companyUserId = -1L;
|
|
|
+ String location = "";
|
|
|
+ // ================================================
|
|
|
+
|
|
|
+ // 构建 WebSocket URL
|
|
|
+ StringBuilder urlBuilder = new StringBuilder();
|
|
|
+ urlBuilder.append(String.format("ws://%s:%d/ws/app/webSocket?liveId=%d&userId=%d&userType=%d",
|
|
|
+ host, port, liveId, userId, userType));
|
|
|
+
|
|
|
+ // 添加 JWT Token
|
|
|
+ urlBuilder.append("&").append(jwtHeader).append("=").append(jwtToken);
|
|
|
+
|
|
|
+ // 添加可选参数
|
|
|
+ if (location != null && !location.isEmpty()) {
|
|
|
+ urlBuilder.append("&location=").append(location);
|
|
|
+ }
|
|
|
+ if (companyId != null && companyId != -1L) {
|
|
|
+ urlBuilder.append("&companyId=").append(companyId);
|
|
|
+ }
|
|
|
+ if (companyUserId != null && companyUserId != -1L) {
|
|
|
+ urlBuilder.append("&companyUserId=").append(companyUserId);
|
|
|
+ }
|
|
|
+
|
|
|
+ String wsUrl = urlBuilder.toString();
|
|
|
+
|
|
|
+ System.out.println("===========================================");
|
|
|
+ System.out.println("WebSocket 连接测试");
|
|
|
+ System.out.println("===========================================");
|
|
|
+ System.out.println("测试时间: " + new java.util.Date());
|
|
|
+ System.out.println("连接地址: " + wsUrl);
|
|
|
+ System.out.println("用户ID: " + userId);
|
|
|
+ System.out.println("直播间ID: " + liveId);
|
|
|
+ System.out.println("用户类型: " + (userType == 0 ? "普通用户" : "管理员"));
|
|
|
+ System.out.println("JWT Header: " + jwtHeader);
|
|
|
+ System.out.println("JWT Token: " + jwtToken.substring(0, Math.min(50, jwtToken.length())) + "...");
|
|
|
+ System.out.println("===========================================\n");
|
|
|
+
|
|
|
+ // 创建 WebSocket 容器
|
|
|
+ container = ContainerProvider.getWebSocketContainer();
|
|
|
+
|
|
|
+ // 设置容器配置
|
|
|
+ container.setDefaultMaxSessionIdleTimeout(60000);
|
|
|
+ container.setDefaultMaxBinaryMessageBufferSize(1024 * 1024);
|
|
|
+ container.setDefaultMaxTextMessageBufferSize(1024 * 1024);
|
|
|
+
|
|
|
+ System.out.println("✓ WebSocket 容器创建成功");
|
|
|
+
|
|
|
+ // 创建客户端实例
|
|
|
+ client = new WebSocketTestClient();
|
|
|
+ System.out.println("✓ 客户端实例创建成功\n");
|
|
|
+
|
|
|
+ System.out.println("正在连接到: " + wsUrl);
|
|
|
+ System.out.println("请稍候...\n");
|
|
|
+
|
|
|
+ // 连接到 WebSocket 服务器
|
|
|
+ long startTime = System.currentTimeMillis();
|
|
|
+ try {
|
|
|
+ container.connectToServer(client, new URI(wsUrl));
|
|
|
+ long connectTime = System.currentTimeMillis() - startTime;
|
|
|
+ System.out.println("✓ 连接请求已发送 (耗时: " + connectTime + "ms)");
|
|
|
+ } catch (Exception e) {
|
|
|
+ long failTime = System.currentTimeMillis() - startTime;
|
|
|
+ System.err.println("✗ 连接请求失败 (耗时: " + failTime + "ms)");
|
|
|
+ throw e;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 等待连接建立(最多等待5秒)
|
|
|
+ System.out.println("等待服务器响应...");
|
|
|
+ for (int i = 0; i < 50; i++) {
|
|
|
+ Thread.sleep(100);
|
|
|
+ if (client.isConnected()) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if (i % 10 == 0 && i > 0) {
|
|
|
+ System.out.print(".");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ System.out.println();
|
|
|
+
|
|
|
+ // 检查连接状态
|
|
|
+ if (!client.isConnected()) {
|
|
|
+ System.err.println("\n❌ 连接未能建立!");
|
|
|
+ if (client.getConnectionError() != null) {
|
|
|
+ System.err.println("连接错误:");
|
|
|
+ client.getConnectionError().printStackTrace();
|
|
|
+ }
|
|
|
+ System.err.println("\n请检查:");
|
|
|
+ System.err.println("1. fs-live-app 服务是否已启动?");
|
|
|
+ System.err.println("2. 服务是否运行在端口 " + port + "?");
|
|
|
+ System.err.println("3. 数据库中是否存在 live_id=" + liveId + " 的直播间?");
|
|
|
+ System.err.println("4. 数据库中是否存在 user_id=" + userId + " 的用户?");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ Scanner scanner = new Scanner(System.in);
|
|
|
+ System.out.println("\n✅ 连接成功!请输入要发送的消息:");
|
|
|
+ System.out.println(" - 输入 'heartbeat' 发送心跳消息");
|
|
|
+ System.out.println(" - 输入其他文本发送聊天消息");
|
|
|
+ System.out.println(" - 输入 'quit' 或 'exit' 退出\n");
|
|
|
+
|
|
|
+ while (true) {
|
|
|
+ System.out.print("> ");
|
|
|
+ String input = scanner.nextLine();
|
|
|
+
|
|
|
+ if ("quit".equalsIgnoreCase(input) || "exit".equalsIgnoreCase(input)) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (input.trim().isEmpty()) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ if ("heartbeat".equalsIgnoreCase(input)) {
|
|
|
+ String heartbeatMsg = String.format(
|
|
|
+ "{\"cmd\":\"heartbeat\",\"liveId\":%d,\"userId\":%d,\"userType\":%d}",
|
|
|
+ liveId, userId, userType
|
|
|
+ );
|
|
|
+ client.sendMessage(heartbeatMsg);
|
|
|
+ } else {
|
|
|
+ String chatMsg = String.format(
|
|
|
+ "{\"cmd\":\"sendMsg\",\"liveId\":%d,\"userId\":%d,\"userType\":%d,\"nickName\":\"测试用户\",\"avatar\":\"\",\"msg\":\"%s\"}",
|
|
|
+ liveId, userId, userType, input
|
|
|
+ );
|
|
|
+ client.sendMessage(chatMsg);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ scanner.close();
|
|
|
+
|
|
|
+ } catch (Exception e) {
|
|
|
+ System.err.println("\n❌ 连接失败: " + e.getClass().getSimpleName() + ": " + e.getMessage());
|
|
|
+
|
|
|
+ // 打印完整堆栈
|
|
|
+ System.err.println("\n📋 完整异常堆栈:");
|
|
|
+ e.printStackTrace();
|
|
|
+
|
|
|
+ // 分析错误原因
|
|
|
+ System.err.println("\n💡 错误分析:");
|
|
|
+ System.err.println("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
|
|
|
+
|
|
|
+ String errorMsg = e.getMessage();
|
|
|
+ if (errorMsg != null) {
|
|
|
+ if (errorMsg.contains("500")) {
|
|
|
+ System.err.println("🔴 HTTP 500 错误 - 服务器内部错误");
|
|
|
+ System.err.println(" 可能原因:");
|
|
|
+ System.err.println(" 1. 服务器端握手处理抛出异常");
|
|
|
+ System.err.println(" 2. 数据库中不存在对应的 liveId 或 userId");
|
|
|
+ System.err.println(" 3. JWT Token 验证失败");
|
|
|
+ System.err.println(" 4. Spring Bean 注入失败");
|
|
|
+ System.err.println();
|
|
|
+ System.err.println(" ✅ 解决方案:");
|
|
|
+ System.err.println(" 1. 查看 fs-live-app 的控制台输出");
|
|
|
+ System.err.println(" 2. 查看日志文件: fs-live-app/logs/");
|
|
|
+ System.err.println(" 3. 确认 liveId=27 是否存在于数据库");
|
|
|
+ System.err.println(" 4. 确认 userId=856648 是否存在于数据库");
|
|
|
+
|
|
|
+ } else if (errorMsg.contains("404")) {
|
|
|
+ System.err.println("🔴 HTTP 404 错误 - 路径不存在");
|
|
|
+ System.err.println(" 可能原因: WebSocket 端点路径错误");
|
|
|
+ System.err.println(" 正确路径: /ws/app/webSocket");
|
|
|
+
|
|
|
+ } else if (errorMsg.contains("401") || errorMsg.contains("403")) {
|
|
|
+ System.err.println("🔴 HTTP " + (errorMsg.contains("401") ? "401" : "403") + " 错误 - 认证失败");
|
|
|
+ System.err.println(" 可能原因: JWT Token 无效或过期");
|
|
|
+ System.err.println(" 解决方案: 重新生成 Token");
|
|
|
+
|
|
|
+ } else if (errorMsg.contains("Connection refused") || errorMsg.contains("ConnectException")) {
|
|
|
+ System.err.println("🔴 连接被拒绝");
|
|
|
+ System.err.println(" 可能原因: 服务未启动或端口错误");
|
|
|
+ System.err.println(" 解决方案:");
|
|
|
+ System.err.println(" 1. 启动 fs-live-app 服务");
|
|
|
+ System.err.println(" 2. 确认服务运行在端口 7114");
|
|
|
+ System.err.println(" 3. 访问 http://localhost:7114 测试");
|
|
|
+
|
|
|
+ } else if (errorMsg.contains("timeout") || errorMsg.contains("Timeout")) {
|
|
|
+ System.err.println("🔴 连接超时");
|
|
|
+ System.err.println(" 可能原因: 网络问题或服务器无响应");
|
|
|
+ System.err.println(" 解决方案: 检查网络连接和服务器状态");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ System.err.println("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
|
|
|
+
|
|
|
+ } finally {
|
|
|
+ if (client != null) {
|
|
|
+ client.close();
|
|
|
+ }
|
|
|
+ System.out.println("\n测试结束");
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|