# WebSocket for iOS 學習筆記 >### Websocket Introduction Before WebSocket appears, to dealing with 2-way data communications, we have some choices such as 'Polling'(輪詢), 'Long Polling'(長時間輪詢) or 'Silent Push Notification'(無聲推播). But, the more 'Polling' we used, the more 'NetWork Request' we caused, and some of them won't even response a new data. Furthermore, sending too much 'Silent Push Notification' isn't that effective, because 'Notification' isn't received at once. 'Long Polling' is the best choice among them, it is the extended version of 'Polling' and will keep an effective link between server and client, but this is also the cons of it, every 'Network Request' will come up with a 'Http OverHead'(Http 開銷), and so, server will need extra maintainance for it's complexity. This is why WebSocket was created, because it doesn't have any 'Http OverHead' protocols, and when client sends a WebSocket connection request to server, it'll create a 2-way connections stream to receive or send data/messages from any side (not through 'Network Request'). ![](https://i.imgur.com/WIIxaee.png) >### Websocket Message - **FIN**: the single bit indicates whether this is the final frame of message or if more frames will follow. - **opcode**: these four bits indicate what type of message this is and how to handle payload data. - non-control frames: ***continuation***, ***text***, ***binary*** - thease deal with how to decode the payload - control frame: ***connection cloase***, ***ping***, ***pong*** - these are special types of messages - when each side receive a '***ping***', it must resend a '***pong***' in a period of time to ensure the connection is still available. - **MASK**: this single bit indicates wheter the message is masked. Client-to-Server messgaes must always be masked. - **Payload length**: use these <span class='blue'>7</span>, <span class='blue'>23</span> or <span class='blue'>71</span> bits to explain how big the payload data is in bits, much like HTTP's Content-Length header. - **masking key**: these four optional bits contain the key you used to mask the message. You can omit them if the **MASK** bit is 0. - **payload data**: the rest of the message contains the actual payload. >### Usages 1. **IM (Instant Messaging)** 2. **Online Games** 3. **Co-Editing Document (ex: HackMD)** 4. **live streams** 5. **stock platforms** 6. **IoT** ## StarScream * Open Resources for Webscoket (<span class="red">iOS 10 or above</span>) * [StarScream](https://github.com/daltoniam/Starscream) ## URLSessionWebSocketTask * only supports <span class="red">iOS 13</span> or above ![](https://i.imgur.com/ccmdUsp.png) * URLSessionWebSocketTask extends URLSessionTask, because it provides a 2-way real-time communication via WebSocket (different from typical HTTP request -> OIOO). >### Basic Steps - 1. **First**, create our WebSocket Connection, this will have server sent back every message it receives. ![](https://i.imgur.com/EQ2hzX3.png) 2. **Second**, to open a connection, we need to resume the webSocketTask ![](https://i.imgur.com/tdOgseC.png) 3. **Then**, you can only send text or binary data, we can't send low-level WebSocket frames like 'ping' or any other control messages, this is fine for most cases, so we can optionally create an enum for this work-flow ![](https://i.imgur.com/cP2ugLq.png) ![](https://i.imgur.com/22Nfax1.png) <font size=2>-> <span class='blue'>server received "Hello Socket" ans sent it back.</span></font> 4. **After that**, to receive data coming from server, we need to use *****URLSessionWebSocketTask.Receive***** method. This method accepts cpmpletion handler that receives a value of new ***Result*** type. ![](https://i.imgur.com/SNQ1QFU.png) the value of the success case is the same as *****URLSessionWebSocketTask.Message***** that we used to send messages. <font size=4><span class='red'> # The tricky part is:</span></font> this ***Receive*** method is only called once, if you want to receive another message, you'll need to call this method again. So the current solution is by adding a 'defer' to it's own handler: ![](https://i.imgur.com/NNA2sww.png) - If your app is not sending message over WebScket within period of time frequency, the server may disconnect your connection due to inactivity, so it's time to use 'PingPong' messages to stay connected. ![](https://i.imgur.com/V5UW5Dc.png) This method is very basic, it sends only a default ping messages and notifies about it's results. For most of the time. API won't allow any customization of ping message payload, but for some special cases like statistic, ping messages with custom payload can be used to deliver additional information to the server. - When we no longer need WebSocket conneciton, we still have to close it properly. **URLSessionWebSocketTask** has a seperate WebSocket-Specific ***cancel*** method. ![](https://i.imgur.com/a0A8NJQ.png) It accepts close coed and optional reason payload, 'Close Code' is used to tell server why this conneciton is disconnecting. - Obviously, we need to knoe when our WebSocket connection is connected or disconnected and why, to do that we need to use ***URLSessionWebSockerDelegate*** ```swift @available(iOS 13.0, *) public protocol URLSessionWebSocketDelegate : URLSessionTaskDelegate { optional func urlSession(_ session: URLSession, webSocketTask: URLSessionWebSocketTask, didOpenWithProtocol protocol: String?) optional func urlSession(_ session: URLSession, webSocketTask: URLSessionWebSocketTask, didCloseWith closeCode: URLSessionWebSocketTask.CloseCode, reason: Data?) ``` It will notfity you when connection was opened or closed with a close code and a reason form the server. >### Resources - [今天我們來聊一聊WebSocket(iOS/Golang)](https://codertw.com/%E7%A8%8B%E5%BC%8F%E8%AA%9E%E8%A8%80/726803/) - [SwiftUI 教學:利用 WebSocket 打造一個 Bitcoin 價格即時更新 App](https://www.appcoda.com.tw/swiftui-websocket/) - [How to use the URLSessionWebSocketTask in Swift](https://appspector.com/blog/websockets-in-ios-using-urlsessionwebsockettask) <style> .blue { color: darkBlue; } .red { color: red; } </style>