Networking, I guess, is one of the features that is used almost in every app. There are a lot of approaches to how we can use some remote resources using a network.
Various architecture styles like (REST or SOAP), secured/non-secured options in combination with different software structures and protocols provide for us a lot of options.
I already wrote a few articles about networking like this one
In most projects we use REST - old, good, cheap, and easy-to-use approach.
REST works almost for everything, except for things where its not work :].
I mean in something that needs a real-time component: games, chats, state observation between a few independent parts - cases when we wait for an event from server-side in other words, and other similar functionality.
the WebSocket Protocol
If u wondering what is a socket, then, we can refer to official doc:
The WebSocket Protocol enables two-way communication between a client running untrusted code in a controlled environment to a remote host that has opted-in to communications from that code. The security model used for this is the origin-based security model commonly used by web browsers. The protocol consists of an opening handshake followed by basic message framing, layered over TCP. The goal of this technology is to provide a mechanism for browser-based applications that need two-way communication with servers that do not rely on opening multiple HTTP connections (e.g., using XMLHttpRequest or <iframe>s and long polling).
There are a lot of interesting moments related to how this protocol works with details, so if u want to know them all - check that link.
As always, one image is better than 1000 words:
I grab this image from the perfect guide available here
URLSession well-known for years (starting from iOS 7). We use it wisely and it’s one of the most known types for iOS developers.
But only starting from iOS 13 do we get URLSessionWebSocketTask. This is the simplest way to use sockets. Simplicity - is a key for this approach.
We can use URLSessionWebSocketTask for communication using ws: or wss: protocol.
“the WebSocket protocol specification defines ws (WebSocket) and wss (WebSocket Secure) as two new uniform resource identifier (URI) schemes that are used for unencrypted and encrypted connections respectively.” - wiki
Another good explanation for ws and wss available on SO
The API is very simple and requires only to create a task, ask to send/receive, and use ping/pong to keep the connection active.
One strange moment in API - after each message u should call receive - to read frames again.
We can easily combine this in some modules. And with Combine it can be even easier to use.
Here is the option how it can be done.
To use - init with address, and call needed functions:
Network framework
URLSession that I mentioned is built on top of this framework.
Use this framework when you need direct access to protocols like TLS, TCP, and UDP for your custom application protocols. Continue to use URLSession, which is built upon this framework, for loading HTTP- and URL-based resources. - as mentioned in official doc
So, we can use this framework to perform socket communication.
As usual, the most interesting stuff from Apple is without a piece of documentation.
With the Network framework u get additional options such as:
configure additional params for connections (for example auto-reply for ping or message size, additional headers, etc)
use IP address or URL (and control additional params)
monitor viability
monitor better path for u’r connection (WebSocketConnection)
The downside - is that u need to write a bit more code.
ping-pong dance is still needed to be done
Here is a minimal implementation of sockets using Network
NSStream
Stream is a class that represents streams in cocoa .] .
Stream objects provide an easy way to read and write data to and from a variety of media in a device-independent way. You can create stream objects for data located in memory, in a file, or on a network (using sockets), and you can use stream objects without loading all of the data into memory at once.
Stream - is just a potentially never-ending data flow.
The last time I used stream - it was, maybe, 3 or 4 years ago. What does this mean? There are a lot of wrappers for this because this is a low-level Unix feature. This means, that usage is not so obvious sometimes and it’s an error-prone process.
Anyway, we still can use it for socket-base communication.
Here is a Stream example
This code is not a drag and use, I grabbed different parts from some project, where I connected to the local device in network - that was and openWRT system with custom PCB for some specific purpose.
Why use CFNetwork if we have a lot of ways to do socket communication? The only reason is only if u need to support some protocols that are not supported by more high-level API (like URLSession).
if u check the official doc - this function already deprecated due to reasons described a bit earlier above
The code with example contains comments-explanation of how to perform connection to specific host with sockets and send message using CFNetwork.
CFNetwork CFSocket example
Testing
To test sockets we need some source that provides sockets for us.
The easiest way - is to create a server and use it on localhost.
To do so, we can use javaScript:
then, just run using node:
With latest example that use CFNetwork u can get something like this:
3rd party
There are a lot of 3rd party libs that provide similar functionality to us, but all of them (or at least 99% of them) under the hood use one of the core components.