투케이2K

138. (TWOK/UTIL) [Ios/Swift] C_WebSocket_Urlsession_Client_Module : urlSession 사용해 WebSocket 웹소켓 통신 본문

투케이2K 유틸파일

138. (TWOK/UTIL) [Ios/Swift] C_WebSocket_Urlsession_Client_Module : urlSession 사용해 WebSocket 웹소켓 통신

투케이2K 2024. 10. 4. 20:13

[설 명]

프로그램 : Ios / Swift

설 명 : C_WebSocket_Urlsession_Client_Module : urlSession 사용해 WebSocket 웹소켓 통신

 

[소스 코드]

 

import Foundation
import UIKit

class C_WebSocket_Urlsession_Client_Module : NSObject, URLSessionWebSocketDelegate {
    
    
    
    /**
     * // -----------------------------------------------------------------------------------------------------------------------------------------------------------------
     * TODO [클래스 설명]
     * // -----------------------------------------------------------------------------------------------------------------------------------------------------------------
     * 1. 웹 소켓 통신 수행 클라이언트 모듈
     * // -----------------------------------------------------------------------------------------------------------------------------------------------------------------
     * 2. 테스트 웹소켓 참고 사이트 :
     *
     * https://www.toolfk.com/ko/tools/online-runwebsocket.html
     * // -----------------------------------------------------------------------------------------------------------------------------------------------------------------
     * */
    
    
    
    
    
    /**
     * // -----------------------------------------------------------------------------------------------------------------------------------------------------------------
     * TODO [소스 코드 사용 방법]
     * // -----------------------------------------------------------------------------------------------------------------------------------------------------------------
     DispatchQueue.main.async { // [비동기 요청]
         
         let tag_ = "웹 소켓 통신 요청"
         
         //let url_ = "wss://javascript.info/article/websocket/demo/hello"
         let url_ = "ws://192.168.0.15:8001"
         
         let header_ : Dictionary<String, Any> = [:]
         
         
         // -----------------------------------------------
         // MARK: [웹 소켓 연결 수행]
         // -----------------------------------------------
         C_WebSocket_Urlsession_Client_Module().startWebsocket(tag: tag_, url: url_, header: header_){(result, response) in
             
             S_Log._F_(description: "웹 소켓 연결 결과 확인", data: [response])
             
             if result == true {
                 
                 
                 // -----------------------------------------------
                 // MARK: [주기적 핑 체크 동작]
                 // -----------------------------------------------
                 C_WebSocket_Urlsession_Client_Module().pingCheck {(result, response) in }
                 
                 
                 // -----------------------------------------------
                 // MARK: [실시간 메시지 수신 확인]
                 // -----------------------------------------------
                 C_WebSocket_Urlsession_Client_Module().onReceive(){(result, response) in
                     
                     S_Log._F_(description: "웹 소켓 실시간 메시지 수신 대기 결과", data: [response])
                     
                     if result == false {
                         
                         C_WebSocket_Urlsession_Client_Module().closeWebSocket(){(result, response) in
                             
                             S_Log._F_(description: "웹 소켓 종료 결과", data: [response])
                             
                         }
                         
                     }
                     else {
                         
                         // MARK: [실시간 메시지 수신 처리]
                         
                     }
                     
                 }
                 
                 
                 // -----------------------------------------------
                 // MARK: [실시간 메시지 전송 수행]
                 // -----------------------------------------------
                 DispatchQueue.main.asyncAfter(deadline: .now() + 5) { // [5초 시간 설정]
                     
                     C_WebSocket_Urlsession_Client_Module().onSend(tag: "HELLO_1 전송", data: "hello_1"){(result, response) in
                         
                         S_Log._F_(description: "웹 소켓 실시간 메시지 송신 결과_1", data: [response])
                         
                     }
                     
                 }
                 
                 
                 // -----------------------------------------------
                 // MARK: [실시간 메시지 전송 수행]
                 // -----------------------------------------------
                 DispatchQueue.main.asyncAfter(deadline: .now() + 10) { // [10초 시간 설정]
                     
                     C_WebSocket_Urlsession_Client_Module().onSend(tag: "HELLO_2 전송", data: "hello_2"){(result, response) in
                         
                         S_Log._F_(description: "웹 소켓 실시간 메시지 송신 결과_2", data: [response])
                         
                     }
                     
                 }
                 
                 
                 // -----------------------------------------------
                 // MARK: [웹 소켓 종료 수행]
                 // -----------------------------------------------

                 DispatchQueue.main.asyncAfter(deadline: .now() + 30) { // [30초 시간 설정]
                     
                     C_WebSocket_Urlsession_Client_Module().closeWebSocket(){(result, response) in
                         
                         S_Log._F_(description: "웹 소켓 종료 결과", data: [response])
                         
                     }
                     
                 }
                 
             }
             
         }
         
     }
     * // -----------------------------------------------------------------------------------------------------------------------------------------------------------------
     * */





    /**
     * // -----------------------------------------------------------------------------------------------------------------------------------------------------------------
     * TODO [빠른 로직 찾기 : 주석 로직 찾기]
     * // -----------------------------------------------------------------------------------------------------------------------------------------------------------------
     * [SEARCH FAST] : startWebsocket
     * // -----------------------------------------------------------------------------------------------------------------------------------------------------------------
     * [SEARCH FAST] : WebSocket Open Delegate
     * // -----------------------------------------------------------------------------------------------------------------------------------------------------------------
     * [SEARCH FAST] : WebSocket onReceive
     * // -----------------------------------------------------------------------------------------------------------------------------------------------------------------
     * [SEARCH FAST] : WebSocket onSend
     * // -----------------------------------------------------------------------------------------------------------------------------------------------------------------
     * [SEARCH FAST] : WebSocket Timer Ping
     * // -----------------------------------------------------------------------------------------------------------------------------------------------------------------
     * [SEARCH FAST] : WebSocket Close
     * // -----------------------------------------------------------------------------------------------------------------------------------------------------------------
     *
     * // -----------------------------------------------------------------------------------------------------------------------------------------------------------------
     */
    
    
    
    
    
    // -----------------------------------------------------------------------------------------
    // MARK: - [전역 변수 선언]
    // -----------------------------------------------------------------------------------------
    private let ACTIVITY_NAME = "C_WebSocket_Urlsession_Client_Module"
    
    var workItem: DispatchWorkItem? = nil
    let PING_TIME_OUT = 10.0
    
    var tag = "" // [태그 지정]
    
    static var webSocketTask: URLSessionWebSocketTask?  = nil // [웹소켓 태스크 지정]
    
    
    
    
    
    // -----------------------------------------------------------------------------------------
    // MARK: - [SEARCH FAST] : startWebsocket
    // -----------------------------------------------------------------------------------------
    private let socketOperationQueue = OperationQueue()
    static var webSocketOpenFlag = false
    static var webSocketOpenMessage = ""
    
    func startWebsocket(tag: String, url: String, header: Dictionary<String, Any>?, callback: @escaping (Bool, String)->()) {
        
        /*
         // -----------------------------------------
         [requestQueriesHttp 메소드 설명]
         // -----------------------------------------
         1. 비동기 POST 방식 graphql HTTP 통신 수행 및 콜백 반환 실시
         // -----------------------------------------
         2. 호출 방법 :
         
         let tag_ = "웹 소켓 통신 요청"
         let url_ = "wss://javascript.info/article/websocket/demo/hello"
         let header_ : Dictionary<String, Any> = [:]
         
         C_WebSocket_Urlsession_Client_Module().startWebsocket(tag: tag_, url: url_, header: header_){(result, response) in
             
             S_Log._F_(description: "웹 소켓 연결 결과 확인", data: [response])
             
         }
         // -----------------------------------------
         3. 사전 설정 사항 :
         
         - 필요 info plist 설정
         [1] http 허용 : App Transport Security Settings >> Allow Arbitrary Loads >> YES
         // -----------------------------------------
         */
        
        
        // -----------------------------------------
        // [초기 값 초기화]
        // -----------------------------------------
        C_WebSocket_Urlsession_Client_Module.webSocketOpenFlag = false
        C_WebSocket_Urlsession_Client_Module.webSocketOpenMessage = "Start"
        self.workItem = nil
        // -----------------------------------------
        
        
        // -----------------------------------------
        // [작업 큐에 추가]
        // -----------------------------------------
        self.socketOperationQueue.isSuspended = true
        let block = { callback(C_WebSocket_Urlsession_Client_Module.webSocketOpenFlag, C_WebSocket_Urlsession_Client_Module.webSocketOpenMessage) }
        self.socketOperationQueue.addOperation(block)
        // -----------------------------------------
        
        
        // -----------------------------------------
        // [사전 방어 로직 체크]
        // -----------------------------------------
        if url.startsWith(_string: "http") == true || url.startsWith(_string: "ws") == true {
        }
        else {
            // [콜백 반환]
            C_WebSocket_Urlsession_Client_Module.webSocketOpenFlag = false
            C_WebSocket_Urlsession_Client_Module.webSocketOpenMessage = self.ACTIVITY_NAME + " :: [startWebsocket] :: [ERROR] :: Url Http Not Start"
            self.socketOperationQueue.isSuspended = false
            return
        }
        // -----------------------------------------
        
        
        // -----------------------------------------
        // [url 선언 실시]
        // -----------------------------------------
        let urlData = String(describing: url)
        // -----------------------------------------
        
        
        // -----------------------------------------
        // [Tag 지정 실시]
        // -----------------------------------------
        self.tag = String(describing: tag)
        // -----------------------------------------
        
        
        // -----------------------------------------
        // [URLRequest 생성 실시]
        // -----------------------------------------
        let urlComponents = URLComponents(string: urlData)
        var requestURL = URLRequest(url: (urlComponents?.url)!)
        
        requestURL.httpMethod = "GET"
        
        requestURL.addValue("application/x-www-form-urlencoded; charset=utf-8;", forHTTPHeaderField: "Content-Type") // header settings
        requestURL.addValue("no-cache", forHTTPHeaderField: "Cache-Control") // header settings
        
        if C_Util().dicNotNull(dic_: header) == true {
            
            for key in header!.keys {
                
                requestURL.addValue("\(String(describing: header![key] ?? ""))", forHTTPHeaderField: "\(key)")
                
            }

        }
        // -----------------------------------------
        
        
        // -----------------------------------------
        // [요청 로그 출력 실시]
        // -----------------------------------------
        S_Log._D_(description: self.ACTIVITY_NAME + " :: [startWebsocket] :: WebSocket Http [요청] 수행", data: [
            "TAG :: " + String(describing: tag),
            "TYPE :: GET >> REQUEST",
            "URL :: " + String(describing: urlData),
            "HEADER :: " + String(describing: header)
        ])
        // -----------------------------------------
        
        
        // -----------------------------------------
        // [http 요쳥을 위한 URLSessionDataTask 생성]
        // -----------------------------------------
        let sessionConfig = URLSessionConfiguration.default
        //sessionConfig.timeoutIntervalForRequest = C_WebSocket_Urlsession_Client_Module.TIME_OUT // [커넥션 타임 아웃 설정]
        //sessionConfig.timeoutIntervalForResource = C_WebSocket_Urlsession_Client_Module.TIME_OUT // [리소스 읽기 , 쓰기]
        
        let session = URLSession(configuration: sessionConfig)
        
        S_FileManager.appHttpLogSave(description: String(describing: tag), request: requestURL, data: nil, response: nil, error: nil)
        // -----------------------------------------
        
        
        // -----------------------------------------
        // [웹 소켓 Task 지정]
        // -----------------------------------------
        C_WebSocket_Urlsession_Client_Module.webSocketTask = session.webSocketTask(with: requestURL)
        
        if #available(iOS 15.0, *) {
            C_WebSocket_Urlsession_Client_Module.webSocketTask?.delegate = self
        } else {
            // [콜백 반환]
            C_WebSocket_Urlsession_Client_Module.webSocketOpenFlag = false
            C_WebSocket_Urlsession_Client_Module.webSocketOpenMessage = self.ACTIVITY_NAME + " :: [startWebsocket] :: [ERROR] :: Ios Version 15 Minor"
            self.socketOperationQueue.isSuspended = false
            return
        }
        // -----------------------------------------
        
        
        // -----------------------------------------
        // [network 통신 실행]
        // -----------------------------------------
        C_WebSocket_Urlsession_Client_Module.webSocketTask!.resume()
        // -----------------------------------------
        
        
        // -----------------------------------------
        // [작업 아이템 지정]
        // -----------------------------------------
        self.workItem = DispatchWorkItem {
            
            // [콜백 반환]
            C_WebSocket_Urlsession_Client_Module.webSocketOpenFlag = false
            C_WebSocket_Urlsession_Client_Module.webSocketOpenMessage = self.ACTIVITY_NAME + " :: [startWebsocket] :: [ERROR] :: Ping Timeout"
            self.socketOperationQueue.isSuspended = false
            return
        }
        
        let delay = DispatchTime.now() + self.PING_TIME_OUT // [특정 시간 후에 실행]
        
        DispatchQueue.main.asyncAfter(deadline: delay, execute: self.workItem!)
        // -----------------------------------------
        
    }
    
    
    
    
    
    // -----------------------------------------------------------------------------------------
    // MARK: - [SEARCH FAST] : WebSocket Open Delegate
    // -----------------------------------------------------------------------------------------
    func urlSession(_ session: URLSession, webSocketTask: URLSessionWebSocketTask, didOpenWithProtocol protocol: String?) {
        
        
        // MARK: [Ping 타임 아웃 예약 작업 취소]
        if (self.workItem != nil){
            self.workItem?.cancel()
            self.workItem = nil
        }
        
        
        // MARK: [웹 소켓 상태 확인]
        switch webSocketTask.state {
        case .running:
            C_WebSocket_Urlsession_Client_Module.webSocketOpenFlag = true
            C_WebSocket_Urlsession_Client_Module.webSocketOpenMessage = self.ACTIVITY_NAME + " :: [urlSession] :: The web socket is running"
        case .suspended:
            C_WebSocket_Urlsession_Client_Module.webSocketOpenFlag = false
            C_WebSocket_Urlsession_Client_Module.webSocketOpenMessage = self.ACTIVITY_NAME + " :: [urlSession] :: The web socket is suspended"
        case .canceling:
            C_WebSocket_Urlsession_Client_Module.webSocketOpenFlag = false
            C_WebSocket_Urlsession_Client_Module.webSocketOpenMessage = self.ACTIVITY_NAME + " :: [urlSession] :: The web socket is canceling"
        case .completed:
            C_WebSocket_Urlsession_Client_Module.webSocketOpenFlag = false
            C_WebSocket_Urlsession_Client_Module.webSocketOpenMessage = self.ACTIVITY_NAME + " :: [urlSession] :: The web socket is completed"
        @unknown default:
            C_WebSocket_Urlsession_Client_Module.webSocketOpenFlag = false
            C_WebSocket_Urlsession_Client_Module.webSocketOpenMessage = self.ACTIVITY_NAME + " :: [urlSession] :: The web socket Unknown state"
        }
        
        
        // MARK: [Task 에러 상태 확인]
        //*
        guard webSocketTask.error == nil else {
            
            C_WebSocket_Urlsession_Client_Module.webSocketOpenFlag = false
            C_WebSocket_Urlsession_Client_Module.webSocketOpenMessage = self.ACTIVITY_NAME + " :: [urlSession] :: [webSocketTask.error] :: \(webSocketTask.error?.localizedDescription ?? "")"
        
            S_Log._E_(description: self.ACTIVITY_NAME + " :: [urlSession] :: WebSocket [didOpenWithProtocol] Open 열기 Error 확인", data: [
                "TAG :: " + String(describing: self.tag),
                "STATUS :: " + String(describing: C_WebSocket_Urlsession_Client_Module.webSocketOpenFlag),
                "MESSAGE :: " + String(describing: C_WebSocket_Urlsession_Client_Module.webSocketOpenMessage),
                "PROTOCOL :: " + String(describing: `protocol`)
            ])
            
            self.socketOperationQueue.isSuspended = false
            
            return
        }
        // */
        
        
        // MARK: [ping 체크 방식으로 연결 상태 확인]

        if C_WebSocket_Urlsession_Client_Module.webSocketOpenFlag == true {
           
            C_WebSocket_Urlsession_Client_Module.webSocketTask?.sendPing(pongReceiveHandler: { error in
                guard error == nil else {
                    
                    C_WebSocket_Urlsession_Client_Module.webSocketOpenFlag = false
                    C_WebSocket_Urlsession_Client_Module.webSocketOpenMessage = self.ACTIVITY_NAME + " :: [urlSession] :: [Ping Error] :: \(error?.localizedDescription ?? "")"
                
                    S_Log._E_(description: self.ACTIVITY_NAME + " :: [urlSession] :: WebSocket [didOpenWithProtocol] Open 열기 Error 확인", data: [
                        "TAG :: " + String(describing: self.tag),
                        "STATUS :: " + String(describing: C_WebSocket_Urlsession_Client_Module.webSocketOpenFlag),
                        "MESSAGE :: " + String(describing: C_WebSocket_Urlsession_Client_Module.webSocketOpenMessage),
                        "PROTOCOL :: " + String(describing: `protocol`)
                    ])
                    
                    self.socketOperationQueue.isSuspended = false
                    
                    return
                }
            
                
                C_WebSocket_Urlsession_Client_Module.webSocketOpenFlag = true
                C_WebSocket_Urlsession_Client_Module.webSocketOpenMessage = self.ACTIVITY_NAME + " :: [urlSession] :: [Ping Success] :: WebSocket Open"
                
                S_Log._W_(description: self.ACTIVITY_NAME + " :: [urlSession] :: WebSocket [didOpenWithProtocol] Open 열기 결과 확인", data: [
                    "TAG :: " + String(describing: self.tag),
                    "STATUS :: " + String(describing: C_WebSocket_Urlsession_Client_Module.webSocketOpenFlag),
                    "MESSAGE :: " + String(describing: C_WebSocket_Urlsession_Client_Module.webSocketOpenMessage),
                    "PROTOCOL :: " + String(describing: `protocol`)
                ])
                
                // [콜백 반환]
                self.socketOperationQueue.isSuspended = false
                
            })
            
        }
        else {
            
            S_Log._E_(description: self.ACTIVITY_NAME + " :: [urlSession] :: WebSocket [didOpenWithProtocol] Open 열기 Fail 확인", data: [
                "TAG :: " + String(describing: self.tag),
                "STATUS :: " + String(describing: C_WebSocket_Urlsession_Client_Module.webSocketOpenFlag),
                "MESSAGE :: " + String(describing: C_WebSocket_Urlsession_Client_Module.webSocketOpenMessage),
                "PROTOCOL :: " + String(describing: `protocol`)
            ])
            
            // [콜백 반환]
            self.socketOperationQueue.isSuspended = false
            
        }
        
    }
    
    
    
    func urlSession(_ session: URLSession, webSocketTask: URLSessionWebSocketTask, didCloseWith closeCode: URLSessionWebSocketTask.CloseCode, reason: Data?) {
        
        S_Log._E_(description: self.ACTIVITY_NAME + " :: [urlSession] :: WebSocket [didCloseWith] Close 닫기 결과 확인", data: [
            "TAG :: " + String(describing: self.tag),
            "CLOSE_CODE :: " + String(describing: closeCode)
        ])
        
        // [콜백 반환]
        C_WebSocket_Urlsession_Client_Module.webSocketOpenFlag = false
        C_WebSocket_Urlsession_Client_Module.webSocketOpenMessage = "Close"
        self.socketOperationQueue.isSuspended = false

    }
    
    
    
    
    
    
    // -----------------------------------------------------------------------------------------
    // MARK: - [SEARCH FAST] : WebSocket onReceive
    // -----------------------------------------------------------------------------------------
    func onReceive(callback: @escaping (Bool, String)->()) {
        S_Log._D_(description: self.ACTIVITY_NAME + " :: [onReceive] :: WebSocket onReceive [메시지 수신] 구독 수행", data: nil)
        
        // -----------------------------------------
        // [사전 방어 로직 작성]
        // -----------------------------------------
        if C_WebSocket_Urlsession_Client_Module.webSocketOpenFlag == false || C_WebSocket_Urlsession_Client_Module.webSocketTask == nil {
            
            // [콜백 반환]
            callback(false, self.ACTIVITY_NAME + " :: [onReceive] :: [ERROR] :: oepn false || socketTask is nil")
            return
        }
        // -----------------------------------------
        
        
        // -----------------------------------------
        // [웹소켓 메시지 수신 상태 확인]
        // -----------------------------------------
        C_WebSocket_Urlsession_Client_Module.webSocketTask!.receive { result in
            switch result {
            case .failure(let error):
                S_Log._E_(description: self.ACTIVITY_NAME + " :: [onReceive] :: webSocketTask.failure :: [메시지 수신] 구독 실패", data: ["Failed to receive message :: \(error)"])
                
                callback(false, self.ACTIVITY_NAME + " :: [onReceive] :: [ERROR] :: " + "Failed to receive message :: \(error)")
                return
            case .success(let message):
                
                switch message {
                case .string(let text):
                    S_Log._D_(description: self.ACTIVITY_NAME + " :: [onReceive] :: webSocketTask.receive :: [메시지 수신] :: string", data: [text])
                    
                    // [콜백 반환]
                    callback(true, text) // MARK: [콜백 반환]
                    
                    // MARK: [중요] : [실시간 메시지 감지 위해 이벤트 재등록]
                    self.onReceive(){(result, response) in
                        callback(result, response) // [콜백 반환]
                    }
                    
                case .data(let data):
                    S_Log._D_(description: self.ACTIVITY_NAME + " :: [onReceive] :: webSocketTask.receive :: [메시지 수신] :: data", data: nil)
                @unknown default:
                    S_Log._D_(description: self.ACTIVITY_NAME + " :: [onReceive] :: webSocketTask.receive :: [메시지 수신] :: @unknown", data: nil)
                }
                
            }
        }
        
    }
    
    
    
    
    
    // -----------------------------------------------------------------------------------------
    // MARK: - [SEARCH FAST] : WebSocket onSend
    // -----------------------------------------------------------------------------------------
    func onSend(tag: String, data: String, callback: @escaping (Bool, String)->()) {
        S_Log._F_(description: self.ACTIVITY_NAME + " :: [onSend] :: WebSocket onSend [메시지 전송] 수행", data: [
            "TAG :: \(tag)",
            "MESSAGE :: \(data)"
        ])
        
        // -----------------------------------------
        // [사전 방어 로직 작성]
        // -----------------------------------------
        if C_WebSocket_Urlsession_Client_Module.webSocketOpenFlag == false || C_WebSocket_Urlsession_Client_Module.webSocketTask == nil {
            
            // [콜백 반환]
            callback(false, self.ACTIVITY_NAME + " :: [onSend] :: [ERROR] :: oepn false || socketTask is nil")
            return
        }
        // -----------------------------------------
        
        
        if C_WebSocket_Urlsession_Client_Module.webSocketTask!.state == .running {
            print(self.ACTIVITY_NAME + " :: [onSend] :: WebSocket onSend [메시지 전송] :: WebSocket is connected == true")
            
            // -----------------------------------------
            // [웹소켓 메시지 전송 수행]
            // -----------------------------------------
            let message = URLSessionWebSocketTask.Message.string(data)
            C_WebSocket_Urlsession_Client_Module.webSocketTask!.send(message) { error in
                if let error = error {
                    
                    // [콜백 반환]
                    callback(false, self.ACTIVITY_NAME + " :: [onSend] :: [ERROR] :: Failed to send message :: \(error)")
                    return
                } else {
                    
                    // [콜백 반환]
                    callback(true, self.ACTIVITY_NAME + " :: [onSend] :: [SUCCESS] :: Send Message")
                    return
                }
            }
            
        } else {
            print(self.ACTIVITY_NAME + " :: [onSend] :: WebSocket onSend [메시지 전송] :: WebSocket is connected == false")
            
            // [콜백 반환]
            callback(false, self.ACTIVITY_NAME + " :: [onSend] :: [ERROR] :: WebSocket is connected == false")
            return
        }

        
    }
    
    
    
    
    
    // -----------------------------------------------------------------------------------------
    // MARK: - [SEARCH FAST] : WebSocket Timer Ping
    // -----------------------------------------------------------------------------------------
    func pingCheck(callback: @escaping (Bool, String)->()) {
        //S_Log._F_(description: self.ACTIVITY_NAME + " :: WebSocket Ping [핑 체크] 수행", data: nil)
        
        // -----------------------------------------
        // [사전 방어 로직 작성]
        // -----------------------------------------
        if C_WebSocket_Urlsession_Client_Module.webSocketOpenFlag == false || C_WebSocket_Urlsession_Client_Module.webSocketTask == nil {
            
            // [콜백 반환]
            callback(false, self.ACTIVITY_NAME + " :: [pingCheck] :: [ERROR] :: oepn false || socketTask is nil")
            return
        }
        // -----------------------------------------
        
        
        // -----------------------------------------
        // [핑 체크 작업 예약]
        // -----------------------------------------
        if C_WebSocket_Urlsession_Client_Module.webSocketTask!.state == .running {
            print(self.ACTIVITY_NAME + " :: [pingCheck] :: WebSocket ping [핑 체크] :: WebSocket is connected == true")
            
            DispatchQueue.main.asyncAfter(deadline: .now() + 10) { // [반복 상태 체크 수행]
                self.pingCheck {(result, response) in }
            }
            
            // -----------------------------------------
            // [핑 체크 수행 실시]
            // -----------------------------------------
            C_WebSocket_Urlsession_Client_Module.webSocketTask?.sendPing(pongReceiveHandler: { error in
                guard error == nil else {
                    S_Log._E_(description: self.ACTIVITY_NAME + " :: [pingCheck] :: WebSocket [Ping Error] :: 핑 체크 에러 발생", data: [
                        "Error :: \(error?.localizedDescription ?? "")"
                    ])

                    // [콜백 반환]
                    callback(false, self.ACTIVITY_NAME + " :: [pingCheck] :: [Ping Error] :: \(error?.localizedDescription ?? "")")
                    return
                }
            
                
                S_Log._W_(description: self.ACTIVITY_NAME + " :: [pingCheck] :: WebSocket [Ping Success] :: 핑 체크 수행 성공", data: nil)

                
                // [콜백 반환]
                callback(true, "")
                return
                
            })
            
        } else {
            print(self.ACTIVITY_NAME + " :: [pingCheck] :: WebSocket ping [핑 체크] :: WebSocket is connected == false")
            
            // [콜백 반환]
            callback(false, self.ACTIVITY_NAME + " :: [pingCheck] :: [Ping Error] :: WebSocket is connected == false)")
            return
        }
        
    }
    
    
    
    
    
    // -----------------------------------------------------------------------------------------
    // MARK: - [SEARCH FAST] : WebSocket Close
    // -----------------------------------------------------------------------------------------
    func closeWebSocket(callback: @escaping (Bool, String)->()) {
        S_Log._D_(description: self.ACTIVITY_NAME + " :: [closeWebSocket] :: WebSocket Close 종료 수행", data: nil)
        
        // -----------------------------------------
        // [사전 방어 로직 작성]
        // -----------------------------------------
        if C_WebSocket_Urlsession_Client_Module.webSocketOpenFlag == false || C_WebSocket_Urlsession_Client_Module.webSocketTask == nil {
            
            // [콜백 반환]
            callback(false, self.ACTIVITY_NAME + " :: [closeWebSocket] :: [ERROR] :: oepn false || socketTask is nil")
            return
        }
        // -----------------------------------------
        
        
        // -----------------------------------------
        // [웹 소켓 종료 수행 및 변수 초기화]
        // -----------------------------------------
        if C_WebSocket_Urlsession_Client_Module.webSocketTask != nil {
            C_WebSocket_Urlsession_Client_Module.webSocketTask?.cancel()
        }
        C_WebSocket_Urlsession_Client_Module.webSocketTask = nil
        C_WebSocket_Urlsession_Client_Module.webSocketOpenFlag = false
        C_WebSocket_Urlsession_Client_Module.webSocketOpenMessage = ""
        self.workItem = nil
        self.tag = ""
        
        // [콜백 반환]
        callback(true, self.ACTIVITY_NAME + " :: [closeWebSocket] :: [WebSocket Close] :: [웹 소켓 종료] :: Success")
        return
        
    }
    

    
} // [클래스 종료]

 

반응형
Comments