丹·雨 2024-09-25 22:55 采纳率: 61.5%
浏览 6

websocket跨域连接失败问题

前端后端需要建立websocket连接,但是出现了跨域问题(应该是跨域问题),局域网内可以连接到,局域网外就只能访问页面但不能建立websocket连接,以下是具体前后端代码(后端使用ipv6地址进行访问)

@ServerEndpoint(value = "/ws/{sid}")
@Slf4j
@Component
public class WebSocketServer {
    private static int onlineCount = 0;
    private static Map<String, WebSocketServer> clients = new ConcurrentHashMap<>();
    private Session session;
    private String sid;

    @OnOpen
    public void onOpen(@PathParam("sid") String sid, Session session) {
        this.sid = sid;
        this.session = session;
        WebSocketServer.onlineCount++;
        clients.put(sid, this);
        log.info("连接到客户端:{}", sid);
    }

    @OnClose
    public void onClose() {
        clients.remove(sid);
        WebSocketServer.onlineCount--;
        log.info("断开连接:{}", sid);
    }

    @OnMessage
    public void onMessage(String message) {
        log.info("收到客户端消息:{}", message);
    }

    @OnError
    public void onError(Session session, Throwable throwable) {
        log.error("WebSocket发生错误:{}", throwable.getMessage());
    }

    public static void sent2Client(UserLoginVO userLoginVO, String sid) {
        WebSocketServer item = clients.get(sid);
        item.session.getAsyncRemote().sendText(JSONUtil.toJsonStr(userLoginVO));
    }
}


```java
/**
 * WebSocket配置类,用于注册WebSocket的Bean
 */
@Configuration
public class WebSocketConfiguration {

    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }

    public void registerStompEndpoints(StompEndpointRegistry registry) {
        //addEndpoint表示添加了一个/socket端点,客户端就可以通过这个端点来进行连接。
        //withSockJS()的作用是开启SockJS支持(指定使用SockJS协议)
        registry.addEndpoint("/socket").setAllowedOrigins("*").withSockJS();
    }
}





```vue
createWebSocket() {
            console.log('创建websocket连接');
            let websocket = null;
            let clientId = Math.random().toString(36).substr(2);

            //判断当前浏览器是否支持WebSocket
            if ('WebSocket' in window) {
                //连接WebSocket节点
                websocket = new WebSocket("ws://[2sge:47e:428:25df:6635:e257:886a:e28c]:8080/ws/" + clientId);
                this.sid = clientId;
                console.log('websocket连接成功');
            } else {
                alert('当前浏览器不支持,请更换浏览器!');
            }

            // 连接成功时
            websocket.onopen = () => {
                console.log('websocket连接成功')
            }
            websocket.onmessage = event => {
                // 后端发送的消息在event.data中
                console.log("接收到后端消息:" + event.data);
                let jsonObj = JSON.parse(event.data);

                this.userLoginVO.id = jsonObj.id;
                sessionStorage.setItem('token', jsonObj.token);
                sessionStorage.setItem('userId', jsonObj.id);
                console.log("nickname:" + jsonObj.nickname);
                this.userLoginVO.nickname = jsonObj.nickname;
                this.userLoginVO.username = jsonObj.username;
                this.userLoginVO.phone = jsonObj.phone;
                this.userLoginVO.avatar = jsonObj.avatar;

                // 跳转音乐页面
                //设置用户信息
                sessionStorage.setItem("nickname", this.userLoginVO.nickname)
                sessionStorage.setItem("avatar", this.userLoginVO.avatar)

                this.$router.push({
                    path: '/music',
                });
            }

            websocket.onclose = function () {
                console.log('关闭了')
            }

            // 路由跳转时结束websocket链接
            this.$router.afterEach(function () {
                //websocket.close()
                console.log('路由跳转')
            })
            // 监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常
            window.onbeforeunload = function () {
                websocket.close()
            }
        },


  • 写回答

2条回答 默认 最新

  • 科技梦想家 2024-09-25 22:56
    关注

    以下内容由AIGC 及 gpt.4o 科技梦想家编程波士 共同为您回答解决方案、有用望采纳☀️☀️:

    在处理 WebSocket 跨域连接失败问题时,主要考虑几个方面,包括后端配置、前端代码、以及网络环境的限制。你的代码片段已经提供了后端和前端的实现,下面是一些可能导致跨域问题及其解决方案的详细分析。
    1. 确认 CORS 配置
      虽然 WebSocket 连接不直接受到 CORS(跨域资源共享)政策的影响,但如果你的后端服务需要配置 CORS,尤其是在你同时使用 HTTP 和 WebSocket 时。你已经在 WebSocketConfiguration 中使用了 setAllowedOrigins("*"),这可以允许所有来源的连接。

    确保你在 WebSocket 配置中也包含了对 HTTP 请求的 CORS 配置。例如:

    java
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.servlet.config.annotation.CorsRegistry;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

    @Configuration
    public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/ws/**")
                .allowedOrigins("*")
                .allowedMethods("GET", "POST", "OPTIONS")
                .allowedHeaders("*")
                .allowCredentials(true);
    }
    

    }
    2. WebSocket URL 的构造
    你在前端 Vue.js 代码中使用了 IPv6 地址。确保这个地址是可以在局域网外被访问的。如果你在局域网内可以连接但在外部不能,可能是因为网络防火墙或路由器设置。

    javascript
    websocket = new WebSocket("ws://[240e:47e:428:25df:10c6:e257:573a:e99c]:8080/ws/" + clientId);
    建议尝试以下几种方式:

    使用 DNS 名称而不是 IP 地址(如果可行)。
    确认外部网络(例如防火墙、路由器等)是否允许该端口的 WebSocket 连接(端口 8080)。
    如果可能,将服务器的地址替换为公共 IP 地址进行测试。
    3. 网络环境与防火墙
    确保你的服务器网络配置正确:

    检查服务器防火墙规则,确保允许来自外部网络的 WebSocket 连接。
    如果在云服务上部署应用,检查云服务提供商的网络安全组配置。
    4. 调试与错误处理
    在前端代码中添加更多的调试信息,可以帮助你更快地找到问题所在。将错误处理添加到 onerror 事件:

    websocket.onerror = function(event) {
        console.error("WebSocket Error: ", event);
    };
    
    
    1. 兼容性与备用方案
      如果 WebSocket 连接仍然无法建立,考虑使用 SockJS 作为一个替代方案,这可以自动处理多种传输方式(如 XHR Streaming 和 XHR Polling),以提高兼容性。

    在后端配置中,确保你添加了 SockJS 支持:

    
    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/socket").setAllowedOrigins("*").withSockJS();
    }
    
    

    并在 Vue.js 端使用 SockJS 客户端库:

    
    import SockJS from 'sockjs-client';
    
    let sock = new SockJS('http://[你的服务器地址]/socket');
    sock.onopen = function() {
        console.log('SockJS连接成功');
    };
    
    

    总结
    检查和配置 CORS。
    确保 WebSocket URL 可访问。
    检查网络和防火墙设置。
    使用调试信息查看错误详情。
    考虑使用 SockJS 作为后备方案。
    这些步骤可以帮助你定位和解决 WebSocket 连接中遇到的跨域问题。如果你还有其他问题或者更详细的错误信息,请提供进一步的细节。

    评论

报告相同问题?

问题事件

  • 修改了问题 9月25日
  • 创建了问题 9月25日

悬赏问题

  • ¥15 如何在vue.config.js中读取到public文件夹下window.APP_CONFIG.API_BASE_URL的值
  • ¥50 浦育平台scratch图形化编程
  • ¥20 求这个的原理图 只要原理图
  • ¥15 vue2项目中,如何配置环境,可以在打完包之后修改请求的服务器地址
  • ¥20 微信的店铺小程序如何修改背景图
  • ¥15 UE5.1局部变量对蓝图不可见
  • ¥15 一共有五道问题关于整数幂的运算还有房间号码 还有网络密码的解答?(语言-python)
  • ¥20 sentry如何捕获上传Android ndk 崩溃
  • ¥15 在做logistic回归模型限制性立方条图时候,不能出完整图的困难
  • ¥15 G0系列单片机HAL库中景园gc9307液晶驱动芯片无法使用硬件SPI+DMA驱动,如何解决?