iosswiftxcodewebsocketstarscream

How to fix "websocket is disconnected: Invalid HTTP upgrade" error using Starscream


I want to connect an iPhone to a web server running on my Macbook using MAMP and Starscream Library https://github.com/daltoniam/Starscream Installed using Cocoapods and set up the web server with this URL:localhost:8888 But I'm having a lot of headaches because the code doesn't work... I followed all the guides online, the official documentation and so on but none of them helped me... Whenever I run the code, the console shows this message: websocket is disconnected: Invalid HTTP upgrade

So maybe it's my server that's broken? I tried using instead ws://echo.websocket.org/ and it worked!!! So I thought... Because it finally showed me: websocket is connected But at the same time it wasn't!!! In fact the method socket.isConnected gave me false... After that if I called socket.disconnect() it doesn't work either, no messages show up.

import UIKit
import Starscream

class ViewController: UIViewController, WebSocketDelegate {

    let socket = WebSocket(url: URL(string:"ws://echo.websocket.org/")!)//websocket is connected
    /*
    let socket = WebSocket(url: URL(string: "ws://localhost:8888/")!) //websocket is disconnected: Invalid HTTP upgrade
    */
    override func viewDidLoad() {
        super.viewDidLoad()

        socket.delegate = self
        socket.connect()

        if socket.isConnected {
            print("hi1") //it doesn't get printed
        }
        if !socket.isConnected {
            print("hi2") //it gets printed
        }

    }

    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)")
    }

}

Solution

  • So I finally understood the problem: Apache doesn't support Web Sockets by default... that's why I got the error message. Then the code works with "ws://echo.websocket.org/". You just have to put all socket.x functions outside viewDidLoad() to make them work, for example socket.disconnect in a Disconnect Button, socket.write in a sendButton etc.

    For example:

    let socket = WebSocket(url: URL(string: "ws://echo.websocket.org/")!) 
    
    override func viewDidLoad() {
        super.viewDidLoad()
    
        socket.delegate = self
        socket.connect()
    
    }
    
    @IBAction func sendButtonPressed(_ sender: UIButton) {
        socket.write(string: textField.text!)
    }