-
Notifications
You must be signed in to change notification settings - Fork 0
URLSessionWebSocketTask
동재 edited this page Dec 14, 2023
·
1 revision
- 스위프트에서 제공하는 URLSessionWebsocketTask에 대해서 학습
- 기존에 많이 사용되었던 외부라이브러리인 [socket.io](http://socket.io) starstream 보다
- 애플에서 제공하는 소켓통신에 대해서 공부해보고싶었습니다.
- URLSessionWebsocketTask
final class WebSocket: NSObject {
static let shared = WebSocket()
var url: URL?
// 연결이 끊겼을 때, 소켓연결도 끊음.
private var webSocketTask: URLSessionWebSocketTask? {
didSet { oldValue?.cancel(with: .goingAway, reason: nil)}
}
private var timer: Timer?
private override init() {}
func openWebSocket() throws {
// URLSessionConfiguration을 통해 헤더를 넣음.
let configuration = URLSessionConfiguration.default
guard let accessToken = JWTManager.shared.get()?.accessToken else { return }
configuration.httpAdditionalHeaders = ["Authorization": "Bearer \(accessToken)"]
guard let url = url else { throw WebSocketError.invalidURL }
let urlSession = URLSession(configuration: configuration)
let webSocketTask = urlSession.webSocketTask(with: url)
// 소켓통신 시작.
webSocketTask.resume()
self.webSocketTask = webSocketTask
self.startPing() // 핑을 통해 소켓 끊김 방지
self.receiveEvent() // receive 이벤트 발생 감지
}
func closeWebSocket() {
self.webSocketTask = nil
self.timer?.invalidate()
}
private func send(data: Data) {
self.webSocketTask?.send(.data(data)) { error in
if let error = error {
print("오류 발생: \(error)")
} else {
print("메시지 전송 완료")
}
}
}
func receiveEvent() {
guard let webSocketTask = self.webSocketTask else {
return
}
webSocketTask.receive { result in
switch result {
case .success(let message):
if case .string(let text) = message {
if let jsonData = text.data(using: .utf8) {
do {
let decoder = JSONDecoder()
let message = try decoder.decode(ReceiveMessageDTO.self, from: jsonData)
MessageManager.shared.messageSubject.send(message)
} catch {
dump(error)
}
}
}
self.receiveEvent()
case .failure(let error):
print("Error receiving message: \(error)")
}
}
}
private func startPing() {
self.timer?.invalidate()
self.timer = Timer.scheduledTimer(
withTimeInterval: 10,
repeats: true,
block: { [weak self] _ in self?.ping() }
)
}
private func ping() {
self.webSocketTask?.sendPing(pongReceiveHandler: { [weak self] error in
guard error != nil else { return }
self?.startPing()
})
}
}
메세지를 json으로 변경해서 send() 호출
func sendJoinRoom(roomID: Int) {
let joinRoomEvent = """
{
"event": "join-room",
"data": {
"room_id": \(roomID)
}
}
"""
guard let jsonData = joinRoomEvent.data(using: .utf8) else { return }
send(data: jsonData)
}
func sendMessage(roomID: Int, sender: String, message: String, count: Int) {
let sendMessageEvent = """
{
"event": "send-message",
"data": {
"room_id": \(roomID),
"message": "\(message)",
"sender": "\(sender)",
"count": \(count)
}
}
"""
guard let jsonData = sendMessageEvent.data(using: .utf8) else { return }
send(data: jsonData)
}