In this post, I’ll share how to build socket application.
Project Structure
I created a workspace and put the Client (SwiftUI) and Server (Vapor)


Server (Vapor)
Server code is very simple. It is only 32 lines of code.
import Vaporfunc routes(_ app: Application) throws { //Endpoint - ws://127.0.0.1:8080/echo app.webSocket("echo") { req, ws in // Connected WebSocket. //Send Ping to Client ws.sendPing() ws.onPong { ws, data in // Pong was received from client print("Connection alive, Received Pong") } ws.onText { ws, text in // String received by this WebSocket. ws.send("👋 Sent Message: \(text) from Server") } ws.onBinary { ws, binary in // [UInt8] received by this WebSocket. print(binary) ws.send("Received Data: \(binary.readableBytes)") } ws.onPing { ws, data in // Ping was received. print("Received Ping") } }}
Client (SwiftUI)
I used URLSessionWebSocketTask.
Here is viewModel logic. This class is @Observale and inherent from NSObject to handle URLSessionWebSocketDelegate.
import SwiftUIimport Foundation@Observable class ContentViewModel: NSObject { var message: String = "" var received: String = "" private var session: URLSession! private var socketTask: URLSessionWebSocketTask! override init() { super.init() self.session = URLSession(configuration: .default, delegate: self, delegateQueue: nil) self.socketTask = session.webSocketTask( with: URL(string: "ws://127.0.0.1:8080/echo")! ) self.socketTask.resume() } func ping() { socketTask.sendPing { error in if let error { print("ping failed: \(error.localizedDescription)") } else { print("pong received") } } } func send() async { try? await socketTask.send(.string(message)) } func receive() async { while let message = try? await socketTask.receive() { switch message { case let .string(receivedMessage): print("Received Message from Server: \(receivedMessage)") received = receivedMessage default: break } } } func disconnect() { socketTask.cancel(with: .goingAway, reason: nil) }}extension ContentViewModel: URLSessionWebSocketDelegate { func urlSession(_ session: URLSession, webSocketTask: URLSessionWebSocketTask, didOpenWithProtocol protocol: String?) { print("Connected") Task { await receive() } } func urlSession(_ session: URLSession, webSocketTask: URLSessionWebSocketTask, didCloseWith closeCode: URLSessionWebSocketTask.CloseCode, reason: Data?) { print("Disconnected: \(closeCode)") }}
SwiftUI Code
import SwiftUIstruct ContentView: View { @State private var viewModel = ContentViewModel() var body: some View { VStack { Text(viewModel.received) Divider() HStack { TextField(text: $viewModel.message) { Text("Message") } Button("Send") { Task { await viewModel.send() } }.padding(4) .background(.blue) .foregroundColor(.white) } Divider() Button("Ping") { viewModel.ping() }.frame( maxWidth: .infinity, maxHeight: 30 ).background(.teal) .foregroundColor(.white) } .padding() }}#Preview { ContentView()}
Let’s run a simple socket application
Both client and server can send a ping. When received the ping message then receiver send a pong message automatically. It’s a way to check status of connections.


If you want to more details about WebSocket, check my post


Leave a Reply