こんにちは。新人プログラマーの岩本です。
今回はNode.jsとSwiftを使って、WebSocket通信を行いたいと思います。
本記事ではWebSocketの基本から、応用として簡易的なチャットアプリを作ります。
ぜひ最後までご覧ください。
WebSocket通信とは
WebSocket通信とは、サーバとクライアントの相互通信を低コストで行うためのプロトコルです。
HTTP通信との違いは、サーバとクライアントのどちらからでも通信を始めることが可能なことです。
HTTPでは、クライアントしかリクエストを送ることができません。なのでSNSなどリアルタイム性を求められるアプリの場合、クライアントから高頻度でリクエストを送る必要があります。
ですが、データの更新がない場合もリクエストが送られるので、サーバの負担になってしまいます。
そこでWebSocket通信が登場しました。WebSocketではどちらからでも通信を開始することができるので、リアルタイムな動作が可能になりました。
Node.jsとSwiftでWebSocket通信を行う
ではここから実際にWebSocket通信を行なっていましょう。
今回サーバーはNode.js、クライアントはSwift(iOSアプリ)で実装します。
またライブラリは「SocketIO」を使用します。
Node.jsの実装
まず適当なフォルダを作り、SocketIOをインストールします。
npm install socket.io
次にapp.js
を作成し、以下のコードを記述します。
var http = require("http");
var server = http.createServer((req, res) => {
res.write("Create server!!");
res.end();
});
// socket.ioの準備
var io = require('socket.io')(server);
// クライアント接続時の処理(io.on)
io.on('connection', (socket) => {
console.log("Client connected!!");
// クライアント切断時の処理
socket.on('disconnect', () => {
console.log("Client disconnected!!");
});
// クライアントからの受信を受ける
socket.on("from_client", (obj) => {
console.log(obj);
});
});
// 一定間隔でサーバ時刻を全クライアントに送る(io.emit)
var send_servertime = () => {
var now = new Date();
io.emit("from_server", now.toLocaleString());
console.log(now.toLocaleString());
setTimeout(send_servertime, 1000); // 1秒ごとにsend_servertimeを実行する
};
send_servertime();
server.listen(8080);
最後に以下のコマンドでサーバを起動し、毎秒ログが表示されていればOKです。
node app.js
iOSアプリの実装
まずSPMで、SocketIO(https://github.com/socketio/socket.io-client-swift)をインストールします。
次にContentView.swift
に以下のコードを記述します。
import SwiftUI
import SocketIO
struct ContentView: View {
private let manager = SocketManager(socketURL: URL(string: "http://127.0.0.1:8080/")!)
private var socket: SocketIOClient!
@State private var messages: [String] = []
init() {
socket = manager.defaultSocket
}
var body: some View {
VStack {
List {
ForEach(messages, id: \\.self) { message in
Text(message)
}
}
.listStyle(.plain)
Button {
socket.emit("from_client", "button_tapped!") // イベントの送信
} label: {
Rectangle()
.frame(width: 150, height: 50)
.foregroundStyle(.blue)
.overlay {
Text("From Client")
.foregroundStyle(.white)
}
}
}
.padding()
.onAppear {
socket.on(clientEvent: .connect) { data, ack in
print("socket connected!")
}
socket.on(clientEvent: .disconnect) { data, ack in
print("socket disconnected")
}
socket.on("from_server") { data, ack in // イベントの受信
if let message = data as? [String] {
messages.append(message[0])
}
}
socket.connect() // WebSocket通信開始
}
.onDisappear {
socket.disconnect() // 通信を切断
}
}
}
アプリを立ち上げ、毎秒ログ情報が取得できていればOKです。
【ステップアップ】簡易的なチャットアプリを作る
ではここから学んだWebSocketの知識を使って、簡易的なチャットアプリを作成していきます。
Node.jsの実装
先ほど使ったフォルダの中にwebsocket_server_chat.js
を作成し、以下のコードを記述します。
var http = require("http");
var server = http.createServer((req, res) => {
res.write("server起動!");
res.end();
});
var io = require("socket.io")(server);
var newMessages = []; // 新たなメッセージを格納する配列
io.on('connection', (socket) => {
console.log("Client connected!!");
// クライアント切断時の処理
socket.on('disconnect', function() {
console.log("Client disconnected!!");
});
// クライアントからの受信を受ける
socket.on("from_client", (message) => {
console.log(message);
newMessages.push(message);
send_new_messages();
});
});
// 新たなメッセージを全クライアントに送る(io.emit)
var send_new_messages = () => {
io.emit("from_server", newMessages);
newMessages = [];
};
server.listen(8080);
新たなメッセージを受信したタイミングで、メッセージをクライアントに送る処理を追加しました。
iOSアプリの実装
ChatView.swift
を作成し、以下のコードを記述します。
struct ChatView: View {
private let manager = SocketManager(socketURL: URL(string: "http://127.0.0.1:8080/")!)
private var socket: SocketIOClient!
@State private var messages: [String] = []
@State private var inputMessage = ""
init() {
socket = manager.defaultSocket
}
var body: some View {
VStack {
LazyVStack {
ScrollView {
ForEach(messages, id: \\.self) { message in
Text(message)
.padding()
}
}
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
HStack {
TextField("", text: $inputMessage)
.padding()
.textFieldStyle(.roundedBorder)
Button {
socket.emit("from_client", inputMessage)
inputMessage = ""
} label: {
Text("送信")
.padding()
.background(Color.blue)
.foregroundStyle(.white)
}
}
}
.onAppear {
socket.on(clientEvent: .connect) { data, ack in
print("socket connected!")
}
socket.on(clientEvent: .disconnect) { data, ack in
print("socket disconnected")
}
socket.on("from_server") { data, ack in
if let newMessages = data as? [[String]] {
newMessages
.flatMap { $0 }
.forEach { messages.append($0) }
}
}
socket.connect()
}
}
}
成功すると、チャットでやり取りできるようになります。
まとめ
今回はNode.jsとSwiftを用いて、WebSocket通信を行う方法を解説しました。
この技術を用いると、チャットアプリやオンラインゲームなど、リアルタイムの処理が必要となるアプリを作成できるようになります。
ぜひご自身の手で色々と試してみてください。
ここまでのご閲覧ありがとうございました!
コメント