【问题标题】:How can I connect to Spring WebSocket server from IOS client?如何从 IOS 客户端连接到 Spring WebSocket 服务器?
【发布时间】:2019-05-04 17:09:34
【问题描述】:

我们正在使用 Spring Boot WebSocket 开发一个聊天应用程序。 用户可以登录到托管在 Tomcat 中的聊天应用程序,并向其他在线用户发送消息。 我们无法从另一个 iOS 客户端连接到同一个聊天应用程序。

下面是我们在服务端和客户端的代码实现

///////////////////////////////////////////
// Server side implementation
///////////////////////////////////////////

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.enableSimpleBroker("/message");
        config.setApplicationDestinationPrefixes("/app");
    }

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

@Configuration
@EnableWebSocketMessageBroker
public class WebsocketConfiguration implements WebSocketMessageBrokerConfigurer {

    private final Logger log = LoggerFactory
            .getLogger(WebsocketConfiguration.class);

    public static final String IP_ADDRESS = "IP_ADDRESS";

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.enableSimpleBroker("/message");
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        log.debug("registering StompEndpoints");
        registry.addEndpoint("/websocket/tracker")
                .setHandshakeHandler(new DefaultHandshakeHandler() {
                    // custom authentication 
                }).withSockJS()
                .setInterceptors(httpSessionHandshakeInterceptor());
    }

    @Bean
    public HandshakeInterceptor httpSessionHandshakeInterceptor() {
        return new HandshakeInterceptor() {

            @Override
            public boolean beforeHandshake(ServerHttpRequest request,
                    ServerHttpResponse response, WebSocketHandler wsHandler,
                    Map<String, Object> attributes) throws Exception {
                if (request instanceof ServletServerHttpRequest) {
                    ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request;
                    attributes.put(IP_ADDRESS,
                            servletRequest.getRemoteAddress());
                }
                return true;
            }

            @Override
            public void afterHandshake(ServerHttpRequest request,
                    ServerHttpResponse response, WebSocketHandler wsHandler,
                    Exception exception) {

            }
        };
    }
}

    ///////////////////////////////////////////
    // Web Client side socket creation code 
    ///////////////////////////////////////////

    var stompClient = null;
    function connect() {

    	if (stompClient != null) {
    		stompClient.disconnect();
    	}

    	var socket = new SockJS(contextPath + '/tracking');
    	stompClient = Stomp.over(socket);
    	stompClient.connect({}, function(frame) {
    		stompClient.subscribe('/message/send/individual/' + loginUserUk,
    				function(response) {
    					var messageBody1 = JSON.parse(response.body);
    					//process with the response

    				});
    	});
    }
/////////////////////////////////////////// // IOS Client side code /////////////////////////////////////////// let host = "xxx.xxx.x.xx:8080/tracking" let socket = WebSocket(url: URL(string: "wss://\(host)/")!, protocols:[]) socket.delegate = self socket.connect() func websocketDidConnect(socket: WebSocketClient) { print("websocket is connected") } func websocketDidDisconnect(socket: WebSocketClient, error: Error?) { if let e = error as? WSError { print("websocket is disconnected: \(e.message)") } else if let e = error { print("websocket is disconnected: \(e.localizedDescription)") } else { print("websocket disconnected") } } func websocketDidReceiveMessage(socket: WebSocketClient, text: String) { print("Received text: \(text)") } func websocketDidReceiveData(socket: WebSocketClient, data: Data) { print("Received data: \(data.count)") }

当我们尝试从 iOS 连接时(在上面的代码 sn-p 中提供),我们收到以下错误:TCP Conn 0x109de3d50 SSLHandshake failed (-9847) websocket is disconnected: The operation could not be completed.

非常感谢任何帮助。提前致谢。

【问题讨论】:

  • 您已将其标记为“swift”,但您发布的代码(客户端)是 JavaScript。此外,您没有提供有关尝试连接到服务器时收到的任何错误消息的信息。如果我们要帮助您,我们需要的不仅仅是“无法连接”。
  • 当我们尝试从 iOS 连接时(在上面的代码 sn-p 中提供),我们收到以下错误:TCP Conn 0x109de3d50 SSLHandshake failed (-9847) websocket is disconnected: The operation could'未完成。
  • 您确定服务器具有有效的 SSL 证书吗?如果您有应用程序的源代码,请尝试将“应用程序传输安全性 > 允许任意加载”暂时设置为“是”,看看是否能解决问题。如果是这样,那么您的服务器具有无效或自签名证书。
  • 谢谢。我们已经从letsencrypt设置了免费的SSL证书。我们还尝试在 IOS 应用程序代码中将“允许任意负载”永久设置为“是”。
  • 您看到的错误肯定是 SSL,因此请检查您的服务器是否配置正确。 Allow Arbitrary Loads 将允许任何 SSL 证书,所以如果这不起作用,那么几乎可以肯定是服务器问题。检查服务器是否确实正确应用了证书(可能需要重新启动)。您网络上的错误防火墙/路由器配置也可能导致 SSL 问题。

标签: swift spring websocket


【解决方案1】:

我认为问题在于您从 iOS 客户端使用的 URL。 Websocket 在 HTTP 之上运行,一旦建立 HTTP 连接,客户端和服务器通过 TCP 进行通信。

当您从浏览器连接客户端时,您所做的只是发起 HTTP 请求。一旦服务器确认请求,它就会与客户端浏览器建立 TCP 连接。这是您使用 SockJS(contextPath + '/tracking'); 的地方通过 TCP 层发送消息。

为了将您的 iOS 客户端连接到同一台服务器,您所要做的就是发送 HTTP 请求,而不是带有“wss:”的请求。只要您从 iOS 客户端使用正确的端点发送请求,就应该没问题。

 let host = "xxx.xxx.x.xx:8080/tracking"
       let socket = WebSocket(url: URL(string: "http://\(host)/")!, protocols:[])
            socket.delegate = self
            socket.connect()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-06-27
    • 1970-01-01
    • 2015-08-29
    • 2020-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多