Notice
Recent Posts
Recent Comments
Link
투케이2K
146. (TWOK/UTIL) [Ios/Swift] C_Udp_NWConnection_Client_Socket_Module : UDP 소켓 통신 모듈 본문
투케이2K 유틸파일
146. (TWOK/UTIL) [Ios/Swift] C_Udp_NWConnection_Client_Socket_Module : UDP 소켓 통신 모듈
투케이2K 2024. 12. 6. 18:12[설 명]
프로그램 : Ios / Swift
설 명 : C_Udp_NWConnection_Client_Socket_Module : UDP 소켓 통신 모듈
[소스 코드]
import Foundation
import UIKit
// -----------------------------------------
//MARK: [네트워크 소켓 통신 사용]
import Network
// -----------------------------------------
class C_Udp_NWConnection_Client_Socket_Module {
/**
* // -----------------------------------------------------------------------------------------------------------------------------------------------------------------
* TODO [클래스 설명]
* // -----------------------------------------------------------------------------------------------------------------------------------------------------------------
* 1. UDP 소켓 통신 클라이언트 모듈
* // -----------------------------------------------------------------------------------------------------------------------------------------------------------------
* 2. NWConnection : ios 12 이상 부터 사용 가능한 애플에서 지원하는 네트워크 프레임 워크입니다
* // -----------------------------------------------------------------------------------------------------------------------------------------------------------------
* 3. NWConnection 는 로컬 엔드포인트와 원격 엔드포인트 간의 양방향 데이터 연결 (TCP , UDP) 을 수행할 수 있습니다
* // -----------------------------------------------------------------------------------------------------------------------------------------------------------------
* 4. NWConnection 를 사용하기 위해서는 import Network 패키지 호출 정의가 필요합니다
* // -----------------------------------------------------------------------------------------------------------------------------------------------------------------
* 5. NWParameters 설정 가능 옵션 : tls , tcp , dtls , udp , quic , quicDatagram
* // -----------------------------------------------------------------------------------------------------------------------------------------------------------------
* 6. 애플 공식 참고 사이트 : https://developer.apple.com/documentation/network/nwconnection
* // -----------------------------------------------------------------------------------------------------------------------------------------------------------------
* */
/**
* // -----------------------------------------------------------------------------------------------------------------------------------------------------------------
* // TODO [빠른 로직 찾기 : 주석 로직 찾기]
* // -----------------------------------------------------------------------------------------------------------------------------------------------------------------
* [SEARCH FAST] : observableSocketConnect : IP , PORT 사용해 소켓 연결 수행
* // -----------------------------------------------------------------------------------------------------------------------------------------------------------------
* [SEARCH FAST] : closeSocketConnect : 소켓 연결 종료 수행
* // -----------------------------------------------------------------------------------------------------------------------------------------------------------------
* [SEARCH FAST] : receiveData : 실시간 소켓 메시지 수신 상태 확인
* // -----------------------------------------------------------------------------------------------------------------------------------------------------------------
* [SEARCH FAST] : observableSendData : 실시간 소켓 메시지 전송 수행
* // -----------------------------------------------------------------------------------------------------------------------------------------------------------------
*
* // -----------------------------------------------------------------------------------------------------------------------------------------------------------------
* */
/**
* // -----------------------------------------------------------------------------------------------------------------------------------------------------------------
* TODO [소스 코드 사용 방법]
* // -----------------------------------------------------------------------------------------------------------------------------------------------------------------
DispatchQueue.main.async { // [비동기 요청]
// [변수 선언 수행]
let ip = "192.168.0.10"
let port = 18501
// [소켓 연결 실시] : UDP 는 비연결성 지향으로 소켓 연결 및 구독 후 메시지 send 전송 시 cancel 처리 되므로 다시 소켓 활성 필요
C_Udp_NWConnection_Client_Socket_Module().observableSocketConnect(ip: ip, port: UInt16(port)){(connectResult) in
S_Log._F_(description: "소켓 연결 확인 수행", data: ["\(connectResult)"])
if connectResult == true {
// [실시간 메시지 전송 수행]
DispatchQueue.main.asyncAfter(deadline: .now() + 5) { // [5초 시간 설정]
C_Udp_NWConnection_Client_Socket_Module().observableSendData(msg: "hello"){(sendResult) in
S_Log._F_(description: "소켓 실시간 메시지 전송 확인", data: ["\(sendResult)"])
}
}
}
else {
S_Log._F_(description: "소켓 연결 에러 메시지", data: ["\(C_Udp_NWConnection_Client_Socket_Module.SOCKET_CONNECT_LOG)"])
}
}
}
* // -----------------------------------------------------------------------------------------------------------------------------------------------------------------
* */
// -----------------------------------------------------------------------------------------
// MARK: - [전역 변수 선언]
// -----------------------------------------------------------------------------------------
private static let ACTIVITY_NAME = "C_Udp_NWConnection_Client_Socket_Module"
let CONNECT_TIME_OUT = 20.0 // [연결 타임 아웃 시간]
lazy var udpOptions: NWProtocolUDP.Options = {
let options = NWProtocolUDP.Options()
// options.preferNoChecksum = true // 체크섬 생략 설정
return options
}()
lazy var parames: NWParameters = {
let parames = NWParameters(dtls: nil, udp: udpOptions)
if let isOption = parames.defaultProtocolStack.internetProtocol as? NWProtocolIP.Options {
isOption.version = .v4 // [ipv4 방식 : 192.168.1.1]
}
parames.preferNoProxies = true
return parames
}()
static var connection: NWConnection? = nil // [소켓 통신 수행 객체]
var workItem: DispatchWorkItem? = nil // [연결 타임 아웃 핸들러]
static var connectFlag = false // [연결 완료 플래그 값]
// -----------------------------------------------------------------------------------------
// MARK: - [SEARCH FAST] : observableSetWifiConnection : 특정 와이파이 SSID , PW 입력 다이렉트 연결 수행
// -----------------------------------------------------------------------------------------
// MARK: UDP 는 비연결성 지향으로 소켓 연결 및 구독 후 메시지 send 전송 시 cancel 처리 되므로 다시 소켓 활성 필요
// -----------------------------------------------------------------------------------------
static var SOCKET_CONNECT_LOG = ""
func observableSocketConnect(ip: String, port: UInt16, completion: @escaping (Bool)->()) {
/*
// -----------------------------------------
[observableSocketConnect 메소드 설명]
// -----------------------------------------
1. IP , PORT 사용해 소켓 연결 수행
// -----------------------------------------
2. 호출 방법 :
C_Udp_NWConnection_Client_Socket_Module().observableSocketConnect(ip: "192.168.1.1", port: 5000){(connectResult) in
S_Log._F_(description: "소켓 연결 확인 수행", data: ["\(connectResult)"])
if connectResult == true {
// [소켓 연결 완료 로직 처리]
}
else {
S_Log._F_(description: "소켓 연결 에러 메시지", data: ["\(C_Udp_NWConnection_Client_Socket_Module.SOCKET_CONNECT_LOG)"])
}
}
// -----------------------------------------
3. 필요 import :
import Network
// -----------------------------------------
*/
// [변수 선언]
C_Udp_NWConnection_Client_Socket_Module.connection = nil
C_Udp_NWConnection_Client_Socket_Module.SOCKET_CONNECT_LOG = ""
self.workItem = nil
C_Udp_NWConnection_Client_Socket_Module.connectFlag = false
// [로직 처리 수행]
DispatchQueue.main.async {
S_Log._D_(description: "소켓 생성 및 연결 수행", data: [ "IP :: \(ip)", "PORT :: \(port)" ])
// [인풋 데이터 널 체크]
if C_Util().stringNotNull(str: ip) == true && port >= 0 {
// ---------------------------------------------
// MARK: [소켓 연결 및 연결 상태 확인]
// ---------------------------------------------
//C_Udp_NWConnection_Client_Socket_Module.connection = NWConnection(host: NWEndpoint.Host(ip), port: NWEndpoint.Port("\(port)")!, using: .udp)
C_Udp_NWConnection_Client_Socket_Module.connection = NWConnection(host: NWEndpoint.Host(ip), port: NWEndpoint.Port("\(port)")!, using: self.parames)
// [연결 상태 업데이트 핸들러 설정]
C_Udp_NWConnection_Client_Socket_Module.connection?.stateUpdateHandler = { state in
switch state {
case .ready:
C_Udp_NWConnection_Client_Socket_Module.SOCKET_CONNECT_LOG = "[Success] : Connection Ready State"
C_Udp_NWConnection_Client_Socket_Module.connectFlag = true
S_Log._W_(description: "소켓 생성 및 연결 성공", data: [
"M_LOG :: \(C_Udp_NWConnection_Client_Socket_Module.SOCKET_CONNECT_LOG)",
"IP :: \(ip)",
"PORT :: \(port)"
])
// ---------------------------------------------
// MARK: [실시간 소켓 메시지 수신 상태 확인]
// ---------------------------------------------
self.receiveData()
// [콜백 반환]
completion(true)
return
case .failed(let error):
C_Udp_NWConnection_Client_Socket_Module.SOCKET_CONNECT_LOG = "[Fail] : Connection Fail State"
S_Log._E_(description: "소켓 생성 및 연결 실패", data: [
"M_LOG :: \(C_Udp_NWConnection_Client_Socket_Module.SOCKET_CONNECT_LOG)",
"Description :: \(error)"
])
// [콜백 반환]
if C_Udp_NWConnection_Client_Socket_Module.connectFlag == false {
completion(false)
}
// [객체 초기화]
if C_Udp_NWConnection_Client_Socket_Module.connection != nil {
C_Udp_NWConnection_Client_Socket_Module.connection = nil
C_Udp_NWConnection_Client_Socket_Module.connectFlag = false
}
return
case .cancelled:
C_Udp_NWConnection_Client_Socket_Module.SOCKET_CONNECT_LOG = "[Cancel] : Connection Cancel State"
S_Log._E_(description: "소켓 생성 및 연결 실패", data: [
"M_LOG :: \(C_Udp_NWConnection_Client_Socket_Module.SOCKET_CONNECT_LOG)"
])
// [콜백 반환]
if C_Udp_NWConnection_Client_Socket_Module.connectFlag == false {
completion(false)
}
// [객체 초기화]
if C_Udp_NWConnection_Client_Socket_Module.connection != nil {
C_Udp_NWConnection_Client_Socket_Module.connection = nil
C_Udp_NWConnection_Client_Socket_Module.connectFlag = false
}
return
default:
break
}
}
// [연결 시작]
C_Udp_NWConnection_Client_Socket_Module.connection?.start(queue: .global())
// ---------------------------------------------
// MARK: [소켓 연결 타임 아웃 처리]
// ---------------------------------------------
self.workItem = DispatchWorkItem {
if C_Udp_NWConnection_Client_Socket_Module.connection != nil && C_Udp_NWConnection_Client_Socket_Module.connectFlag == false {
C_Udp_NWConnection_Client_Socket_Module.SOCKET_CONNECT_LOG = "[Time Out] : Socket Connection TimeOut"
S_Log._E_(description: "소켓 생성 및 연결 실패", data: [
"M_LOG :: \(C_Udp_NWConnection_Client_Socket_Module.SOCKET_CONNECT_LOG)"
])
// [UDP 연결 취소]
C_Udp_NWConnection_Client_Socket_Module.connection?.cancel()
}
}
let delay = DispatchTime.now() + self.CONNECT_TIME_OUT // [특정 시간 후에 실행]
DispatchQueue.main.asyncAfter(deadline: delay, execute: self.workItem!)
}
else {
C_Udp_NWConnection_Client_Socket_Module.SOCKET_CONNECT_LOG = "[Error] : Input Data Is Null"
S_Log._E_(description: "소켓 생성 및 연결 에러", data: [
"M_LOG :: \(C_Udp_NWConnection_Client_Socket_Module.SOCKET_CONNECT_LOG)"
])
completion(false) // [콜백 반환]
return
}
}
}
// -----------------------------------------------------------------------------------------
// MARK: - [SEARCH FAST] : closeSocketConnect : 소켓 연결 종료 수행
// -----------------------------------------------------------------------------------------
func closeSocketConnect() {
if C_Udp_NWConnection_Client_Socket_Module.connection != nil {
S_Log._E_(description: "소켓 연결 종료 수행 [IF]", data: nil)
C_Udp_NWConnection_Client_Socket_Module.connection?.cancel()
C_Udp_NWConnection_Client_Socket_Module.connection = nil
C_Udp_NWConnection_Client_Socket_Module.connectFlag = false
}
else {
S_Log._E_(description: "소켓 연결 종료 수행 [ELSE]", data: nil)
}
}
// -----------------------------------------------------------------------------------------
// MARK: - [SEARCH FAST] : receiveData : 실시간 소켓 메시지 수신 상태 확인
// -----------------------------------------------------------------------------------------
// MARK: UDP 는 비연결성 지향으로 소켓 연결 및 구독 후 메시지 send 전송 시 cancel 처리 되므로 다시 소켓 활성 필요
// -----------------------------------------------------------------------------------------
static var RECEIVE_ERROR_LOG = ""
private func receiveData() {
if C_Udp_NWConnection_Client_Socket_Module.connection != nil {
S_Log._D_(description: "소켓 실시간 메시지 수신 감지 수행", data: nil)
C_Udp_NWConnection_Client_Socket_Module.connection?.receive(minimumIncompleteLength: 1, maximumLength: 1024, completion: { data, _, isComplete, error in
// ---------------------------------------------
// MARK: [실시간 메시지 수신 확인]
// ---------------------------------------------
if let data = data, !data.isEmpty {
let message = String(data: data, encoding: .utf8) ?? ""
S_Log._W_(description: "[Ing] ---- [소켓 실시간 메시지 수신 감지] ---- [Ing]", data: [
"message :: \(message)"
])
// ---------------------------------------------
// MARK: [로직 분기 처리]
// ---------------------------------------------
}
// ---------------------------------------------
// MARK: [계속해서 실시간 메시지 수신 처리]
// ---------------------------------------------
if isComplete {
C_Udp_NWConnection_Client_Socket_Module.RECEIVE_ERROR_LOG = "[Error] : Connection closed by server"
S_Log._E_(description: "소켓 실시간 메시지 수신 감지 에러", data: [
"M_LOG :: \(C_Udp_NWConnection_Client_Socket_Module.RECEIVE_ERROR_LOG)"
])
// ---------------------------------------------
// MARK: [소켓 연결 종료 및 객체 초기화]
// ---------------------------------------------
C_Udp_NWConnection_Client_Socket_Module.connection?.cancel()
//C_Udp_NWConnection_Client_Socket_Module.connection = nil
//C_Udp_NWConnection_Client_Socket_Module.connectFlag = false
} else if let error = error {
C_Udp_NWConnection_Client_Socket_Module.RECEIVE_ERROR_LOG = "[Error] : let error catch"
S_Log._E_(description: "소켓 실시간 메시지 수신 감지 에러", data: [
"M_LOG :: \(C_Udp_NWConnection_Client_Socket_Module.RECEIVE_ERROR_LOG)",
"Description :: \(error)"
])
// ---------------------------------------------
// MARK: [소켓 연결 종료 및 객체 초기화]
// ---------------------------------------------
C_Udp_NWConnection_Client_Socket_Module.connection?.cancel()
//C_Udp_NWConnection_Client_Socket_Module.connection = nil
//C_Udp_NWConnection_Client_Socket_Module.connectFlag = false
} else {
// ---------------------------------------------
// [계속해서 데이터 수신]
// ---------------------------------------------
self.receiveData()
}
})
}
else {
S_Log._E_(description: "소켓 실시간 메시지 수신 감지 에러 :: connection is null", data: nil)
}
}
// -----------------------------------------------------------------------------------------
// MARK: - [SEARCH FAST] : observableSendData : 실시간 소켓 메시지 전송 수행
// -----------------------------------------------------------------------------------------
// MARK: UDP 는 비연결성 지향으로 소켓 연결 및 구독 후 메시지 send 전송 시 cancel 처리 되므로 다시 소켓 활성 필요
// -----------------------------------------------------------------------------------------
static var SEND_ERROR_LOG = ""
func observableSendData(msg:String, completion: @escaping (Bool)->()) {
/*
// -----------------------------------------
[observableSendData 메소드 설명]
// -----------------------------------------
1. 실시간 소켓 메시지 전송 수행
// -----------------------------------------
2. 호출 방법 :
C_Udp_NWConnection_Client_Socket_Module().observableSendData(msg: "hello"){(sendResult) in
S_Log._F_(description: "소켓 실시간 메시지 전송 확인", data: ["\(sendResult)"])
if sendResult == true {
}
else {
S_Log._F_(description: "소켓 실시간 메시지 전송 에러 메시지", data: ["\(C_Udp_NWConnection_Client_Socket_Module.SEND_ERROR_LOG)"])
}
}
// -----------------------------------------
3. 필요 import :
import Network
// -----------------------------------------
*/
// [변수 선언]
C_Udp_NWConnection_Client_Socket_Module.SEND_ERROR_LOG = ""
// [로직 처리 수행]
DispatchQueue.global().sync {
if C_Udp_NWConnection_Client_Socket_Module.connection != nil && C_Util().stringNotNull(str: msg) == true {
S_Log._D_(description: "소켓 클라이언트 >> 서버 메시지 전송 수행", data: nil)
// ---------------------------------------------
// MARK: [String To Byte 데이터 전송 수행]
// ---------------------------------------------
let data = msg.data(using: .utf8) ?? Data() // [string to byte]
C_Udp_NWConnection_Client_Socket_Module.connection?.send(content: data, completion: .contentProcessed { error in
if let error = error {
C_Udp_NWConnection_Client_Socket_Module.SEND_ERROR_LOG = "[Error] : Socket Send Message Error"
S_Log._E_(description: "소켓 실시간 메시지 전송 에러", data: [
"M_LOG :: \(C_Udp_NWConnection_Client_Socket_Module.SEND_ERROR_LOG)",
"Description :: \(error)"
])
completion(false) // [콜백 반환]
return
} else {
S_Log._W_(description: "소켓 실시간 메시지 전송 성공", data: [
"msg :: \(msg)"
])
completion(true) // [콜백 반환]
return
}
})
}
else {
C_Udp_NWConnection_Client_Socket_Module.SEND_ERROR_LOG = "[Error] : Input Send Message Is Null"
S_Log._E_(description: "소켓 실시간 메시지 전송 에러", data: [
"M_LOG :: \(C_Udp_NWConnection_Client_Socket_Module.SEND_ERROR_LOG)"
])
completion(false) // [콜백 반환]
return
}
}
}
} // [클래스 종료]
반응형
'투케이2K 유틸파일' 카테고리의 다른 글
Comments