WebSocket has become more and more popular in recent years, and Apple also announced iOS 13 with WebSocket functionality at WWDC 2019. This article will introduce how to use URLSessionWebSocketTask and the Starsream to connect to a WebSocket server.
The complete code can be found in .
URLSessionWebSocketTask
URLSessionWebSocketTask
is available on iOS 13, so make sure that Xcode’s iOS Deployment Target is set after 13.
Opening Connections
Declare a request with URLRequest(url:)
, and call URLSession.webSocketTask(with:)
to create a task. It returns URLSessionWebSocketTask
, start the task by calling .resume()
to open a connection. It’s simple, isn’t it!
guard let url = URL(string: "wss://echo.websocket.org/") else { print("Error: can not create URL") return } let request = URLRequest(url: url) let webSocketTask = URLSession.shared.webSocketTask(with: request) webSocketTask.resume()
Sending Messages
Set a message to be sent into URLSessionWebSocketTask.Message
, and call URLSessionWebSocketTask.send()
to send the message.
let message = URLSessionWebSocketTask.Message.string("Hello WebSocket") webSocketTask.send(message) { error in if let error = error { print(error) } }
Receiving Messages
URLSessionWebSocketTask.receive()
is used to receive messages. it process one message at a time. Received messages are type of URLSessionWebSocketTask.Message
.
It should be noted that when you call .receive()
, it will only receive one message once. So after the handler has processed one message, remember to call .receive()
again before leaving.
private func receive() { webSocketTask.receive { result in switch result { case .success(let message): switch message { case .string(let text): print("Received string: \(text)") case .data(let data): print("Received data: \(data)") @unknown default: fatalError() } case .failure(let error): print(error) } self.receive() } }
Disconnecting
Call URLSessionWebSocketTask.cancel()
to disconnect the connection.
webSocketTask.cancel(with: .goingAway, reason: nil)
Monitoring Connection Statuses
If you want to monitor a connection status, you need to implement URLSessionWebSocketDelegate
. It monitors two events, one is triggered when the connection is opened, and the other is triggered when the connection is disconnected.
extension URLSessionWebSocket: URLSessionWebSocketDelegate { public func urlSession(_ session: URLSession, webSocketTask: URLSessionWebSocketTask, didOpenWithProtocol protocol: String?) { print("URLSessionWebSocketTask is connected") } public func urlSession(_ session: URLSession, webSocketTask: URLSessionWebSocketTask, didCloseWith closeCode: URLSessionWebSocketTask.CloseCode, reason: Data?) { let reasonString: String if let reason = reason, let string = String(data: reason, encoding: .utf8) { reasonString = string } else { reasonString = "" } print("URLSessionWebSocketTask is closed: code=\(closeCode), reason=\(reasonString)") } }
URLSessionWebSocketDelegate
has to be set to URLSession
at the beginning . Therefore, you need to declare a URLSession
yourself when opening a connection, but not use URLSession.defualt
.
let urlSession = URLSession(configuration: .default, delegate: self, delegateQueue: .main) let request = URLRequest(url: url) webSocketTask = urlSession.webSocketTask(with: request) webSocketTask.resume()
Starsream
URLSessionWebSocketTask
looks good to use, but it has some problems. First, it is only available after iOS 13. iOS 13 is still new. We hope that iPhone users who have not upgraded can also install our App. The other is that URLSessionWebSocketTask
is not very convenient in the way of receiving messages and monitoring events. Starsream can solve the above problems for us.
First, install Starsram framework. If you are using CocoaPods, put this line in your Podfile.
pod 'Starscream', '~> 4.0.0'
If you are not familiar with CocoaPods operation, you can refer to this article.
Opening Connections
Declare a WebSocket
with an URL, and call .connect()
to open a connection.
import Starscream guard let url = URL(string: "wss://echo.websocket.org/") else { print("Error: can not create URL") return } let request = URLRequest(url: url) webSocket = WebSocket(request: request) webSocket.connect()
Sending Messages
Call WebSocket.write(string:)
to send a message. Compared with URLSessionWebSocketTask
, it is really much simpler!
webSocket.write(string: message)
Receiving Messages and Monitoring Connection Statuses
Starscream handles message reception and connection status by using events. In particular for message reception, it’s much more intuitive than URLSessionWebSocketTask
.
webSocket.delegate = self extension StarscreamWebSocket: WebSocketDelegate { func didReceive(event: WebSocketEvent, client: WebSocket) { switch event { case .connected(_): print("WebSocket is connected") case .disconnected(let reason, let code): print("Disconnected: code=\(code), reason=\(reason)") case .text(let message): print("Received: \(message)") case .binary(_): break case .pong(_): break case .ping(_): break case .error(let error): print(error ?? "") case .viabilityChanged(_): break case .reconnectSuggested(_): break case .cancelled: print("WebSocket is cancelled") } } }
Disconnecting
Call WebSocket.disconnect()
to disconnect a connection.
webSocket.disconnect()
Conclusion
We describe how to implement WebSocket through URLSessionWebSocketTask
and Starscream. Comparing these two methods, we would recommend Starscream. While URLSessionWebSocketTask
is built in iOS SDK, but its use and popularity are far less than Starscream.