투케이2K

575. (ios/swift5) [간단 소스] NWConnection 사용해 Websocket 웹소켓 연결 방법 본문

IOS

575. (ios/swift5) [간단 소스] NWConnection 사용해 Websocket 웹소켓 연결 방법

투케이2K 2024. 12. 1. 00:13

[개발 환경 설정]

개발 툴 : XCODE

개발 언어 : SWIFT5

 

[소스 코드]

 

// --------------------------------------------------------------------------------------
[개발 및 테스트 환경]
// --------------------------------------------------------------------------------------

- 언어 : Swift


- 개발 툴 : Xcode


- NWConnection 설명 :

  >> NWConnection 는 로컬 엔드포인트와 원격 엔드포인트 간의 양방향 데이터 연결 (TCP , UDP) 을 수행할 수 있습니다

  >> NWConnection 를 사용하기 위해서는 import Network 패키지 호출 정의가 필요합니다

  >> NWParameters 설정 가능 옵션 : 

   - tls
   - tcp
   - dtls
   - udp
   - quic
   - quicDatagram

// --------------------------------------------------------------------------------------






// --------------------------------------------------------------------------------------
[소스 코드]
// --------------------------------------------------------------------------------------

// ----------------------------------------
// MARK: - [전역 변수 선언]
// ----------------------------------------
private static let ACTIVITY_NAME = "C_WebSocket_NMConnection_Client_Module"

let CONNECT_TIME_OUT = 30.0 // [연결 타임 아웃 시간]

static var connection: NWConnection? = nil // [소켓 통신 수행 객체]
var workItem: DispatchWorkItem? = nil // [연결 타임 아웃 핸들러]
static var connectFlag = false // [연결 완료 플래그 값]




// ----------------------------------------
// MARK: - [SEARCH FAST] : observableSocketConnect : IP , PORT 사용해 소켓 연결 수행
// ----------------------------------------
// MARK: [https : wss = 443 / http : ws = 80]
// ----------------------------------------
static var SOCKET_CONNECT_LOG = ""
func observableSocketConnect(url: String, completion: @escaping (Bool)->()) {
    
    /*
    // -----------------------------------------
    [observableSocketConnect 메소드 설명]
    // -----------------------------------------
    1. IP , PORT 사용해 웹 소켓 연결 수행
    // -----------------------------------------
    2. 호출 방법 :
        
        C_WebSocket_NMConnection_Client_Module().observableSocketConnect(url: "wss://example.com"){(connectResult) in
            
            S_Log._F_(description: "웹 소켓 연결 확인 수행", data: ["\(connectResult)"])

            if connectResult == true {
            
            // [웹 소켓 연결 완료 로직 처리]
            }
            else {
            S_Log._F_(description: "웹 소켓 연결 에러 메시지", data: ["\(C_WebSocket_NMConnection_Client_Module.SOCKET_CONNECT_LOG)"])
            }
            
        }
        
    // -----------------------------------------
    3. 필요 import :
        
        import Network
    // -----------------------------------------
    */


    // [변수 선언]
    C_WebSocket_NMConnection_Client_Module.connection = nil
    C_WebSocket_NMConnection_Client_Module.SOCKET_CONNECT_LOG = ""
    self.workItem = nil
    C_WebSocket_NMConnection_Client_Module.connectFlag = false
    
    
    // [로직 처리 수행]
    DispatchQueue.main.async {
        S_Log._D_(description: "웹 소켓 생성 및 연결 수행", data: [ "URL :: \(url)" ])
        
        
        // [인풋 데이터 널 체크]
        if C_Util().stringNotNull(str: url) == true {

            // ---------------------------------------------
            // MARK: [URL 유효성 검증]
            // ---------------------------------------------
            if url.startsWith(_string: "ws") == false {
                C_WebSocket_NMConnection_Client_Module.SOCKET_CONNECT_LOG = "[Error] : Invalid URL"
                    
                S_Log._D_(description: "웹 소켓 생성 및 연결 실패", data: [
                    "M_LOG :: \(C_WebSocket_NMConnection_Client_Module.SOCKET_CONNECT_LOG)",
                    "URL :: \(url)"
                ])
                
                // [콜백 반환]
                if C_WebSocket_NMConnection_Client_Module.connectFlag == false {
                    
                    completion(false)
                    
                }
                
                // [객체 초기화]
                if C_WebSocket_NMConnection_Client_Module.connection != nil {
                    
                    C_WebSocket_NMConnection_Client_Module.connection = nil
                    C_WebSocket_NMConnection_Client_Module.connectFlag = false
                    
                }
                return
            }
            

            // ---------------------------------------------
            // MARK: [소켓 연결 및 연결 상태 확인]
            // ---------------------------------------------

            // [기본 NWParameters (TLS 포함)]
            let parameters = NWParameters.tls
        

            // [WebSocket 옵션 설정]
            let webSocketOptions = NWProtocolWebSocket.Options()
        
        
            // [자동 Ping-Pong 활성화]
            webSocketOptions.autoReplyPing = true
        

            // [WebSocket 기본 헤더 추가 (필요 시 사용자 정의 헤더 설정 가능)]
            /*
            webSocketOptions.setAdditionalHeaders([
                "Authorization": "Bearer YOUR_TOKEN",
                "Custom-Header": "Value"
            ])
            // */
        

            // [WebSocket 프로토콜을 프로토콜 스택에 추가]
            parameters.defaultProtocolStack.applicationProtocols.insert(webSocketOptions, at: 0)


            // [연결 객체 생성]

            C_WebSocket_NMConnection_Client_Module.connection = NWConnection(to: .url(URL(string: url)!), using: parameters)


            // [연결 상태 업데이트 핸들러 설정]
            C_WebSocket_NMConnection_Client_Module.connection?.stateUpdateHandler = { state in
                switch state {
                case .ready:
                    C_WebSocket_NMConnection_Client_Module.SOCKET_CONNECT_LOG = "[Success] : Connection Ready State"
                    C_WebSocket_NMConnection_Client_Module.connectFlag = true
                    
                    S_Log._D_(description: "웹 소켓 생성 및 연결 성공", data: [
                        "M_LOG :: \(C_WebSocket_NMConnection_Client_Module.SOCKET_CONNECT_LOG)",
                        "URL :: \(url)"
                    ])
                    
                    // ---------------------------------------------
                    // MARK: [실시간 메시지 수신 상태 확인]
                    // ---------------------------------------------
                    //self.receiveData()
                    
                    // [콜백 반환]
                    completion(true)
                    return
                    
                case .failed(let error):
                    C_WebSocket_NMConnection_Client_Module.SOCKET_CONNECT_LOG = "[Fail] : Connection Fail State"
                    
                    S_Log._D_(description: "웹 소켓 생성 및 연결 실패", data: [
                        "M_LOG :: \(C_WebSocket_NMConnection_Client_Module.SOCKET_CONNECT_LOG)",
                        "Description :: \(error)"
                    ])
                    
                    // [콜백 반환]
                    if C_WebSocket_NMConnection_Client_Module.connectFlag == false {
                        
                        completion(false)
                        
                    }
                    
                    // [객체 초기화]
                    if C_WebSocket_NMConnection_Client_Module.connection != nil {
                        
                        C_WebSocket_NMConnection_Client_Module.connection = nil
                        C_WebSocket_NMConnection_Client_Module.connectFlag = false
                        
                    }
                    
                    return
                    
                case .cancelled:
                    C_WebSocket_NMConnection_Client_Module.SOCKET_CONNECT_LOG = "[Cancel] : Connection Cancel State"
                    
                    S_Log._D_(description: "웹 소켓 생성 및 연결 실패", data: [
                        "M_LOG :: \(C_WebSocket_NMConnection_Client_Module.SOCKET_CONNECT_LOG)"
                    ])
                    
                    // [콜백 반환]
                    if C_WebSocket_NMConnection_Client_Module.connectFlag == false {
                        
                        completion(false)
                        
                    }
                    
                    // [객체 초기화]
                    if C_WebSocket_NMConnection_Client_Module.connection != nil {
                        
                        C_WebSocket_NMConnection_Client_Module.connection = nil
                        C_WebSocket_NMConnection_Client_Module.connectFlag = false
                        
                    }
                    
                    return
                    
                default:
                    break
                }
            }

            
            // ---------------------------------------------
            // [연결 시작]
            // ---------------------------------------------
            C_WebSocket_NMConnection_Client_Module.connection?.start(queue: .global())
            
            
            // ---------------------------------------------
            // MARK: [웹 소켓 연결 타임 아웃 처리]
            // ---------------------------------------------
            self.workItem = DispatchWorkItem {
                
                if C_WebSocket_NMConnection_Client_Module.connection != nil && C_WebSocket_NMConnection_Client_Module.connectFlag == false {
                    
                    C_WebSocket_NMConnection_Client_Module.SOCKET_CONNECT_LOG = "[Time Out] : Socket Connection TimeOut"
                    
                    S_Log._D_(description: "웹 소켓 생성 및 연결 실패", data: [
                        "M_LOG :: \(C_WebSocket_NMConnection_Client_Module.SOCKET_CONNECT_LOG)"
                    ])
                    
                    // [웹 소켓 연결 취소]
                    C_WebSocket_NMConnection_Client_Module.connection?.cancel()
                    
                }
                
            }
            
            let delay = DispatchTime.now() + self.CONNECT_TIME_OUT // [특정 시간 후에 실행]
            
            DispatchQueue.main.asyncAfter(deadline: delay, execute: self.workItem!)
            
        }
        else {
            C_WebSocket_NMConnection_Client_Module.SOCKET_CONNECT_LOG = "[Error] : Input Data Is Null"
            
            S_Log._D_(description: "웹 소켓 생성 및 연결 에러", data: [
                "M_LOG :: \(C_WebSocket_NMConnection_Client_Module.SOCKET_CONNECT_LOG)"
            ])
            completion(false) // [콜백 반환]
            return
            
        }
    }
    
}

// --------------------------------------------------------------------------------------

 

반응형
Comments