Real-Time Communication with Streams Tutorial for iOS
Get down to TCP-level networking and learn about sockets and how to use Core Foundation to build a real-time chat app in this iOS streams tutorial. By Brody Eller.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Real-Time Communication with Streams Tutorial for iOS
25 mins
- Why Sockets?
- Getting Started
- Getting Your Server to Run
- Looking at the Existing App
- Creating a Chat Room
- Creating Input and Output Streams
- Opening a Connection
- Joining the Chat
- The Communication Protocol
- Reacting to Incoming Messages
- Handling the Incoming Messages
- Creating the ChatRoomDelegate Protocol
- Sending Messages
- Cleaning up After Yourself
- Where to Go From Here?
- UDP Sockets
- WebSockets
- Beej's Guide to Network Programming
From the dawn of time, man has dreamed of better ways to communicate with his brethren far and wide. From carrier pigeons to radio waves, we’re forever trying to communicate more clearly and effectively.
In this modern age, one technology has emerged as an essential tool in our quest for mutual understanding: The humble network socket.
Existing somewhere in layer 4 of our modern networking infrastructure, sockets are at the core of any online communication, from texting to online gaming.
Why Sockets?
You may wonder, “Why do I need to go lower level than URLSession
in the first place?” (If you’re not wondering that, then go ahead and pretend you were.)
Great question! The thing about communicating with URLSession
is that it’s based on the HTTP networking protocol. With HTTP, communication happens in a request-response style. This means that the majority of the networking code in most apps follows the same pattern:
- Request some JSON from a server.
- Receive and use said JSON in a callback or delegate method.
But what about when you want the server to be able to tell your app something? That doesn’t really work very well with HTTP.
Of course, you can make it work by continually pinging the server and seeing if it has updates — aka polling — or you can get a little more crafty and use a technique like long-polling. But these techniques can feel a little unnatural, and each has its own pitfalls.
At the end of the day, why limit yourself to this request-response paradigm if it’s not the right tool for the job?
In this iOS streams tutorial, you’ll learn how to drop down a level of abstraction and use sockets directly to create a real-time chat room app.
Instead of each client having to check the server for new messages, your chat room app will use input and output streams that remain open for the duration of the chat session.
Getting Started
To begin, download the starter materials by using the Download Materials button at the top or bottom of the tutorial. The starter materials include both the chat app and a simple server written in Go.
You won’t have to worry about writing any Go code yourself, but you’ll need to get this server up and running in order to write a client for it.
Getting Your Server to Run
The server in the starter materials uses Go and is pre-compiled for you. If you’re not the kind of person who trusts a pre-compiled executable you found on the web, you can use the source code from the starter materials to compile it yourself.
To run the pre-compiled server, open Terminal, navigate to the starter materials directory and enter this command:
sudo ./server
When the prompt appears, enter your password. After putting your password in, you should see: Listening on 127.0.0.1:80.
sudo
command — because it listens on port 80. All port numbers less than 1024 are privileged ports, requiring root access to bind to them.Your chat server is ready to go! You can now skip to the next section.
If you want to compile the server yourself, you’ll need to install Go with Homebrew.
If you don’t have Homebrew either, then you’ll have to install it before you can start. Open Terminal and paste in the following line:
/usr/bin/ruby -e \
"$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
Then, use this command to install Go:
brew install go
Once that’s finished, navigate to the directory of the starter materials and build the server with build
.
go build server.go
Finally, you can start your server using the command listed at the start of this section.
Looking at the Existing App
Next, open the DogeChat project and build and run it to get a look at what’s already built for you.
As shown above, DogeChat is currently set up to allow a user to enter a username and then go into a chat room.
Unfortunately, the last person to work on it wasn’t sure how to write a chat app, so all you get is the UI and basic plumbing; you must implement the networking layer.
Creating a Chat Room
To get started on the actual coding, navigate to ChatRoomViewController.swift. Here you can see you have a view controller that’s ready and able to receive strings as messages from the input bar. It can also display messages via a table view with custom cells you configure with Message
objects.
Since you already have a ChatRoomViewController
, it makes sense to create a ChatRoom
class to take care of the heavy lifting.
Before you start to write a new class, make a quick list of what its responsibilities will be. You’ll want this class to take care of the following tasks:
- Opening a connection to the chat room server.
- Allowing a user to join the chat room by providing a username.
- Allowing a user to send and receive messages.
- Closing the connection when you’re done.
Now that you know what you want, press Command-N to create a new file. Choose Swift File and name it ChatRoom.
Creating Input and Output Streams
Next, replace the code in ChatRoom.swift with:
import UIKit
class ChatRoom: NSObject {
//1
var inputStream: InputStream!
var outputStream: OutputStream!
//2
var username = ""
//3
let maxReadLength = 4096
}
Here, you’ve defined the ChatRoom
class and declared the properties you’ll need to communicate.
- First, you declare your input and output streams. Using this pair of classes together allows you to create a socket-based connection between your app and the chat server. Naturally, you’ll send messages via the output stream and receive them via the input stream.
- Next, you define
username
, where you’ll store the name of the current user. - Finally, you declare
maxReadLength
. This constant puts a cap on how much data you can send in any single message.
Next, go over to ChatRoomViewController.swift and add a chat room property to the list of properties at the top.
let chatRoom = ChatRoom()
Now that you’ve set up the basic structure of your class, it’s time to knock out the first thing in your checklist: Opening a connection between the app and the server.